authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-12-21 22:18:19-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-12-24 01:18:47-07:00
log42b4a48bc96ce22562230cd1a266f93a013c76dd
tree16a176b415131a12b72cbac682d0398fa65d9926
parent0fd68f49e2eabb866ea1d21c4657c2a1d3c8ce53

WIP start adding support for TSAN


220 files changed, 72299 insertions(+), 3 deletions(-)

CMakeLists.txt+1
...@@ -537,6 +537,7 @@ set(ZIG_STAGE2_SOURCES...@@ -537,6 +537,7 @@ set(ZIG_STAGE2_SOURCES
537 "${CMAKE_SOURCE_DIR}/src/ir.zig"537 "${CMAKE_SOURCE_DIR}/src/ir.zig"
538 "${CMAKE_SOURCE_DIR}/src/libc_installation.zig"538 "${CMAKE_SOURCE_DIR}/src/libc_installation.zig"
539 "${CMAKE_SOURCE_DIR}/src/libcxx.zig"539 "${CMAKE_SOURCE_DIR}/src/libcxx.zig"
540 "${CMAKE_SOURCE_DIR}/src/libtsan.zig"
540 "${CMAKE_SOURCE_DIR}/src/libunwind.zig"541 "${CMAKE_SOURCE_DIR}/src/libunwind.zig"
541 "${CMAKE_SOURCE_DIR}/src/link.zig"542 "${CMAKE_SOURCE_DIR}/src/link.zig"
542 "${CMAKE_SOURCE_DIR}/src/link/C.zig"543 "${CMAKE_SOURCE_DIR}/src/link/C.zig"
lib/tsan/interception/interception.h created+304
...@@ -0,0 +1,304 @@
1//===-- interception.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 AddressSanitizer, an address sanity checker.
10//
11// Machinery for providing replacements/wrappers for system functions.
12//===----------------------------------------------------------------------===//
13
14#ifndef INTERCEPTION_H
15#define INTERCEPTION_H
16
17#include "sanitizer_common/sanitizer_internal_defs.h"
18
19#if !SANITIZER_LINUX && !SANITIZER_FREEBSD && !SANITIZER_MAC && \
20 !SANITIZER_NETBSD && !SANITIZER_OPENBSD && !SANITIZER_WINDOWS && \
21 !SANITIZER_FUCHSIA && !SANITIZER_RTEMS && !SANITIZER_SOLARIS
22# error "Interception doesn't work on this operating system."
23#endif
24
25// These typedefs should be used only in the interceptor definitions to replace
26// the standard system types (e.g. SSIZE_T instead of ssize_t)
27typedef __sanitizer::uptr SIZE_T;
28typedef __sanitizer::sptr SSIZE_T;
29typedef __sanitizer::sptr PTRDIFF_T;
30typedef __sanitizer::s64 INTMAX_T;
31typedef __sanitizer::u64 UINTMAX_T;
32typedef __sanitizer::OFF_T OFF_T;
33typedef __sanitizer::OFF64_T OFF64_T;
34
35// How to add an interceptor:
36// Suppose you need to wrap/replace system function (generally, from libc):
37// int foo(const char *bar, double baz);
38// You'll need to:
39// 1) define INTERCEPTOR(int, foo, const char *bar, double baz) { ... } in
40// your source file. See the notes below for cases when
41// INTERCEPTOR_WITH_SUFFIX(...) should be used instead.
42// 2) Call "INTERCEPT_FUNCTION(foo)" prior to the first call of "foo".
43// INTERCEPT_FUNCTION(foo) evaluates to "true" iff the function was
44// intercepted successfully.
45// You can access original function by calling REAL(foo)(bar, baz).
46// By default, REAL(foo) will be visible only inside your interceptor, and if
47// you want to use it in other parts of RTL, you'll need to:
48// 3a) add DECLARE_REAL(int, foo, const char*, double) to a
49// header file.
50// However, if the call "INTERCEPT_FUNCTION(foo)" and definition for
51// INTERCEPTOR(..., foo, ...) are in different files, you'll instead need to:
52// 3b) add DECLARE_REAL_AND_INTERCEPTOR(int, foo, const char*, double)
53// to a header file.
54
55// Notes: 1. Things may not work properly if macro INTERCEPTOR(...) {...} or
56// DECLARE_REAL(...) are located inside namespaces.
57// 2. On Mac you can also use: "OVERRIDE_FUNCTION(foo, zoo)" to
58// effectively redirect calls from "foo" to "zoo". In this case
59// you aren't required to implement
60// INTERCEPTOR(int, foo, const char *bar, double baz) {...}
61// but instead you'll have to add
62// DECLARE_REAL(int, foo, const char *bar, double baz) in your
63// source file (to define a pointer to overriden function).
64// 3. Some Mac functions have symbol variants discriminated by
65// additional suffixes, e.g. _$UNIX2003 (see
66// https://developer.apple.com/library/mac/#releasenotes/Darwin/SymbolVariantsRelNotes/index.html
67// for more details). To intercept such functions you need to use the
68// INTERCEPTOR_WITH_SUFFIX(...) macro.
69
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
73// 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.
78//
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.
83// Instead we create a dylib containing a __DATA,__interpose section that
84// 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.
88// As it's decided at compile time which functions are to be intercepted on Mac,
89// INTERCEPT_FUNCTION() is effectively a no-op on this system.
90
91#if SANITIZER_MAC
92#include <sys/cdefs.h> // For __DARWIN_ALIAS_C().
93
94// Just a pair of pointers.
95struct interpose_substitution {
96 const __sanitizer::uptr replacement;
97 const __sanitizer::uptr original;
98};
99
100// For a function foo() create a global pair of pointers { wrap_foo, foo } in
101// the __DATA,__interpose section.
102// As a result all the calls to foo() will be routed to wrap_foo() at runtime.
103#define INTERPOSER(func_name) __attribute__((used)) \
104const interpose_substitution substitution_##func_name[] \
105 __attribute__((section("__DATA, __interpose"))) = { \
106 { reinterpret_cast<const uptr>(WRAP(func_name)), \
107 reinterpret_cast<const uptr>(func_name) } \
108}
109
110// For a function foo() and a wrapper function bar() create a global pair
111// of pointers { bar, foo } in the __DATA,__interpose section.
112// As a result all the calls to foo() will be routed to bar() at runtime.
113#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) } \
118}
119
120# define WRAP(x) wrap_##x
121# define WRAPPER_NAME(x) "wrap_"#x
122# define INTERCEPTOR_ATTRIBUTE
123# define DECLARE_WRAPPER(ret_type, func, ...)
124
125#elif SANITIZER_WINDOWS
126# define WRAP(x) __asan_wrap_##x
127# define WRAPPER_NAME(x) "__asan_wrap_"#x
128# define INTERCEPTOR_ATTRIBUTE __declspec(dllexport)
129# define DECLARE_WRAPPER(ret_type, func, ...) \
130 extern "C" ret_type func(__VA_ARGS__);
131# define DECLARE_WRAPPER_WINAPI(ret_type, func, ...) \
132 extern "C" __declspec(dllimport) ret_type __stdcall func(__VA_ARGS__);
133#elif SANITIZER_RTEMS
134# define WRAP(x) x
135# define WRAPPER_NAME(x) #x
136# define INTERCEPTOR_ATTRIBUTE
137# define DECLARE_WRAPPER(ret_type, func, ...)
138#elif SANITIZER_FREEBSD || SANITIZER_NETBSD
139# define WRAP(x) __interceptor_ ## x
140# define WRAPPER_NAME(x) "__interceptor_" #x
141# define INTERCEPTOR_ATTRIBUTE __attribute__((visibility("default")))
142// FreeBSD's dynamic linker (incompliantly) gives non-weak symbols higher
143// priority than weak ones so weak aliases won't work for indirect calls
144// in position-independent (-fPIC / -fPIE) mode.
145# define DECLARE_WRAPPER(ret_type, func, ...) \
146 extern "C" ret_type func(__VA_ARGS__) \
147 __attribute__((alias("__interceptor_" #func), visibility("default")));
148#elif !SANITIZER_FUCHSIA
149# define WRAP(x) __interceptor_ ## x
150# define WRAPPER_NAME(x) "__interceptor_" #x
151# define INTERCEPTOR_ATTRIBUTE __attribute__((visibility("default")))
152# define DECLARE_WRAPPER(ret_type, func, ...) \
153 extern "C" ret_type func(__VA_ARGS__) \
154 __attribute__((weak, alias("__interceptor_" #func), visibility("default")));
155#endif
156
157#if SANITIZER_FUCHSIA
158// There is no general interception at all on Fuchsia.
159// Sanitizer runtimes just define functions directly to preempt them,
160// and have bespoke ways to access the underlying libc functions.
161# include <zircon/sanitizer.h>
162# define INTERCEPTOR_ATTRIBUTE __attribute__((visibility("default")))
163# define REAL(x) __unsanitized_##x
164# define DECLARE_REAL(ret_type, func, ...)
165#elif SANITIZER_RTEMS
166# define REAL(x) __real_ ## x
167# define DECLARE_REAL(ret_type, func, ...) \
168 extern "C" ret_type REAL(func)(__VA_ARGS__);
169#elif !SANITIZER_MAC
170# define PTR_TO_REAL(x) real_##x
171# define REAL(x) __interception::PTR_TO_REAL(x)
172# define FUNC_TYPE(x) x##_type
173
174# define DECLARE_REAL(ret_type, func, ...) \
175 typedef ret_type (*FUNC_TYPE(func))(__VA_ARGS__); \
176 namespace __interception { \
177 extern FUNC_TYPE(func) PTR_TO_REAL(func); \
178 }
179# define ASSIGN_REAL(dst, src) REAL(dst) = REAL(src)
180#else // SANITIZER_MAC
181# define REAL(x) x
182# define DECLARE_REAL(ret_type, func, ...) \
183 extern "C" ret_type func(__VA_ARGS__);
184# define ASSIGN_REAL(x, y)
185#endif // SANITIZER_MAC
186
187#if !SANITIZER_FUCHSIA && !SANITIZER_RTEMS
188# define DECLARE_REAL_AND_INTERCEPTOR(ret_type, func, ...) \
189 DECLARE_REAL(ret_type, func, __VA_ARGS__) \
190 extern "C" ret_type WRAP(func)(__VA_ARGS__);
191// Declare an interceptor and its wrapper defined in a different translation
192// unit (ex. asm).
193# define DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(ret_type, func, ...) \
194 extern "C" ret_type WRAP(func)(__VA_ARGS__); \
195 extern "C" ret_type func(__VA_ARGS__);
196#else
197# define DECLARE_REAL_AND_INTERCEPTOR(ret_type, func, ...)
198# define DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(ret_type, func, ...)
199#endif
200
201// Generally, you don't need to use DEFINE_REAL by itself, as INTERCEPTOR
202// macros does its job. In exceptional cases you may need to call REAL(foo)
203// without defining INTERCEPTOR(..., foo, ...). For example, if you override
204// foo with an interceptor for other function.
205#if !SANITIZER_MAC && !SANITIZER_FUCHSIA && !SANITIZER_RTEMS
206# define DEFINE_REAL(ret_type, func, ...) \
207 typedef ret_type (*FUNC_TYPE(func))(__VA_ARGS__); \
208 namespace __interception { \
209 FUNC_TYPE(func) PTR_TO_REAL(func); \
210 }
211#else
212# define DEFINE_REAL(ret_type, func, ...)
213#endif
214
215#if SANITIZER_FUCHSIA
216
217// We need to define the __interceptor_func name just to get
218// sanitizer_common/scripts/gen_dynamic_list.py to export func.
219// But we don't need to export __interceptor_func to get that.
220#define INTERCEPTOR(ret_type, func, ...) \
221 extern "C"[[ gnu::alias(#func), gnu::visibility("hidden") ]] ret_type \
222 __interceptor_##func(__VA_ARGS__); \
223 extern "C" INTERCEPTOR_ATTRIBUTE ret_type func(__VA_ARGS__)
224
225#elif !SANITIZER_MAC
226
227#define INTERCEPTOR(ret_type, func, ...) \
228 DEFINE_REAL(ret_type, func, __VA_ARGS__) \
229 DECLARE_WRAPPER(ret_type, func, __VA_ARGS__) \
230 extern "C" \
231 INTERCEPTOR_ATTRIBUTE \
232 ret_type WRAP(func)(__VA_ARGS__)
233
234// We don't need INTERCEPTOR_WITH_SUFFIX on non-Darwin for now.
235#define INTERCEPTOR_WITH_SUFFIX(ret_type, func, ...) \
236 INTERCEPTOR(ret_type, func, __VA_ARGS__)
237
238#else // SANITIZER_MAC
239
240#define INTERCEPTOR_ZZZ(suffix, ret_type, func, ...) \
241 extern "C" ret_type func(__VA_ARGS__) suffix; \
242 extern "C" ret_type WRAP(func)(__VA_ARGS__); \
243 INTERPOSER(func); \
244 extern "C" INTERCEPTOR_ATTRIBUTE ret_type WRAP(func)(__VA_ARGS__)
245
246#define INTERCEPTOR(ret_type, func, ...) \
247 INTERCEPTOR_ZZZ(/*no symbol variants*/, ret_type, func, __VA_ARGS__)
248
249#define INTERCEPTOR_WITH_SUFFIX(ret_type, func, ...) \
250 INTERCEPTOR_ZZZ(__DARWIN_ALIAS_C(func), ret_type, func, __VA_ARGS__)
251
252// Override |overridee| with |overrider|.
253#define OVERRIDE_FUNCTION(overridee, overrider) \
254 INTERPOSER_2(overridee, WRAP(overrider))
255#endif
256
257#if SANITIZER_WINDOWS
258# define INTERCEPTOR_WINAPI(ret_type, func, ...) \
259 typedef ret_type (__stdcall *FUNC_TYPE(func))(__VA_ARGS__); \
260 namespace __interception { \
261 FUNC_TYPE(func) PTR_TO_REAL(func); \
262 } \
263 extern "C" \
264 INTERCEPTOR_ATTRIBUTE \
265 ret_type __stdcall WRAP(func)(__VA_ARGS__)
266#endif
267
268// ISO C++ forbids casting between pointer-to-function and pointer-to-object,
269// so we use casting via an integral type __interception::uptr,
270// assuming that system is POSIX-compliant. Using other hacks seem
271// challenging, as we don't even pass function type to
272// INTERCEPT_FUNCTION macro, only its name.
273namespace __interception {
274#if defined(_WIN64)
275typedef unsigned long long uptr;
276#else
277typedef unsigned long uptr;
278#endif // _WIN64
279} // namespace __interception
280
281#define INCLUDED_FROM_INTERCEPTION_LIB
282
283#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \
284 SANITIZER_OPENBSD || SANITIZER_SOLARIS
285
286# include "interception_linux.h"
287# define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func)
288# define INTERCEPT_FUNCTION_VER(func, symver) \
289 INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver)
290#elif SANITIZER_MAC
291# include "interception_mac.h"
292# define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_MAC(func)
293# define INTERCEPT_FUNCTION_VER(func, symver) \
294 INTERCEPT_FUNCTION_VER_MAC(func, symver)
295#elif SANITIZER_WINDOWS
296# include "interception_win.h"
297# define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_WIN(func)
298# define INTERCEPT_FUNCTION_VER(func, symver) \
299 INTERCEPT_FUNCTION_VER_WIN(func, symver)
300#endif
301
302#undef INCLUDED_FROM_INTERCEPTION_LIB
303
304#endif // INTERCEPTION_H
lib/tsan/interception/interception_linux.h created+53
...@@ -0,0 +1,53 @@
1//===-- interception_linux.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 AddressSanitizer, an address sanity checker.
10//
11// Linux-specific interception methods.
12//===----------------------------------------------------------------------===//
13
14#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \
15 SANITIZER_OPENBSD || SANITIZER_SOLARIS
16
17#if !defined(INCLUDED_FROM_INTERCEPTION_LIB)
18# error "interception_linux.h should be included from interception library only"
19#endif
20
21#ifndef INTERCEPTION_LINUX_H
22#define INTERCEPTION_LINUX_H
23
24namespace __interception {
25bool InterceptFunction(const char *name, uptr *ptr_to_real, uptr func,
26 uptr wrapper);
27bool InterceptFunction(const char *name, const char *ver, uptr *ptr_to_real,
28 uptr func, uptr wrapper);
29} // namespace __interception
30
31#define INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func) \
32 ::__interception::InterceptFunction( \
33 #func, \
34 (::__interception::uptr *) & REAL(func), \
35 (::__interception::uptr) & (func), \
36 (::__interception::uptr) & WRAP(func))
37
38// Android, Solaris and OpenBSD do not have dlvsym
39#if !SANITIZER_ANDROID && !SANITIZER_SOLARIS && !SANITIZER_OPENBSD
40#define INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) \
41 ::__interception::InterceptFunction( \
42 #func, symver, \
43 (::__interception::uptr *) & REAL(func), \
44 (::__interception::uptr) & (func), \
45 (::__interception::uptr) & WRAP(func))
46#else
47#define INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) \
48 INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func)
49#endif // !SANITIZER_ANDROID && !SANITIZER_SOLARIS
50
51#endif // INTERCEPTION_LINUX_H
52#endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD ||
53 // SANITIZER_OPENBSD || SANITIZER_SOLARIS
lib/tsan/interception/interception_mac.h created+27
...@@ -0,0 +1,27 @@
1//===-- interception_mac.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 AddressSanitizer, an address sanity checker.
10//
11// Mac-specific interception methods.
12//===----------------------------------------------------------------------===//
13
14#if SANITIZER_MAC
15
16#if !defined(INCLUDED_FROM_INTERCEPTION_LIB)
17# error "interception_mac.h should be included from interception.h only"
18#endif
19
20#ifndef INTERCEPTION_MAC_H
21#define INTERCEPTION_MAC_H
22
23#define INTERCEPT_FUNCTION_MAC(func)
24#define INTERCEPT_FUNCTION_VER_MAC(func, symver)
25
26#endif // INTERCEPTION_MAC_H
27#endif // SANITIZER_MAC
lib/tsan/interception/interception_win.h created+83
...@@ -0,0 +1,83 @@
1//===-- interception_linux.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 AddressSanitizer, an address sanity checker.
10//
11// Windows-specific interception methods.
12//===----------------------------------------------------------------------===//
13
14#if SANITIZER_WINDOWS
15
16#if !defined(INCLUDED_FROM_INTERCEPTION_LIB)
17# error "interception_win.h should be included from interception library only"
18#endif
19
20#ifndef INTERCEPTION_WIN_H
21#define INTERCEPTION_WIN_H
22
23namespace __interception {
24// All the functions in the OverrideFunction() family return true on success,
25// false on failure (including "couldn't find the function").
26
27// Overrides a function by its address.
28bool OverrideFunction(uptr old_func, uptr new_func, uptr *orig_old_func = 0);
29
30// Overrides a function in a system DLL or DLL CRT by its exported name.
31bool OverrideFunction(const char *name, uptr new_func, uptr *orig_old_func = 0);
32
33// Windows-only replacement for GetProcAddress. Useful for some sanitizers.
34uptr InternalGetProcAddress(void *module, const char *func_name);
35
36// Overrides a function only when it is called from a specific DLL. For example,
37// this is used to override calls to HeapAlloc/HeapFree from ucrtbase without
38// affecting other third party libraries.
39bool OverrideImportedFunction(const char *module_to_patch,
40 const char *imported_module,
41 const char *function_name, uptr new_function,
42 uptr *orig_old_func);
43
44#if !SANITIZER_WINDOWS64
45// Exposed for unittests
46bool OverrideFunctionWithDetour(
47 uptr old_func, uptr new_func, uptr *orig_old_func);
48#endif
49
50// Exposed for unittests
51bool OverrideFunctionWithRedirectJump(
52 uptr old_func, uptr new_func, uptr *orig_old_func);
53bool OverrideFunctionWithHotPatch(
54 uptr old_func, uptr new_func, uptr *orig_old_func);
55bool OverrideFunctionWithTrampoline(
56 uptr old_func, uptr new_func, uptr *orig_old_func);
57
58// Exposed for unittests
59void TestOnlyReleaseTrampolineRegions();
60
61} // namespace __interception
62
63#if defined(INTERCEPTION_DYNAMIC_CRT)
64#define INTERCEPT_FUNCTION_WIN(func) \
65 ::__interception::OverrideFunction(#func, \
66 (::__interception::uptr)WRAP(func), \
67 (::__interception::uptr *)&REAL(func))
68#else
69#define INTERCEPT_FUNCTION_WIN(func) \
70 ::__interception::OverrideFunction((::__interception::uptr)func, \
71 (::__interception::uptr)WRAP(func), \
72 (::__interception::uptr *)&REAL(func))
73#endif
74
75#define INTERCEPT_FUNCTION_VER_WIN(func, symver) INTERCEPT_FUNCTION_WIN(func)
76
77#define INTERCEPT_FUNCTION_DLLIMPORT(user_dll, provider_dll, func) \
78 ::__interception::OverrideImportedFunction( \
79 user_dll, provider_dll, #func, (::__interception::uptr)WRAP(func), \
80 (::__interception::uptr *)&REAL(func))
81
82#endif // INTERCEPTION_WIN_H
83#endif // SANITIZER_WINDOWS
lib/tsan/sanitizer_common/sancov_flags.h created+39
...@@ -0,0 +1,39 @@
1//===-- sancov_flags.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// Sanitizer Coverage runtime flags.
10//
11//===----------------------------------------------------------------------===//
12#ifndef SANCOV_FLAGS_H
13#define SANCOV_FLAGS_H
14
15#include "sanitizer_flag_parser.h"
16#include "sanitizer_internal_defs.h"
17
18namespace __sancov {
19
20struct SancovFlags {
21#define SANCOV_FLAG(Type, Name, DefaultValue, Description) Type Name;
22#include "sancov_flags.inc"
23#undef SANCOV_FLAG
24
25 void SetDefaults();
26};
27
28extern SancovFlags sancov_flags_dont_use_directly;
29
30inline SancovFlags* sancov_flags() { return &sancov_flags_dont_use_directly; }
31
32void InitializeSancovFlags();
33
34} // namespace __sancov
35
36extern "C" SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE const char*
37__sancov_default_options();
38
39#endif
lib/tsan/sanitizer_common/sancov_flags.inc created+20
...@@ -0,0 +1,20 @@
1//===-- sancov_flags.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// Sanitizer Coverage runtime flags.
10//
11//===----------------------------------------------------------------------===//
12#ifndef SANCOV_FLAG
13#error "Defnine SANCOV_FLAG prior to including this file!"
14#endif
15
16SANCOV_FLAG(bool, symbolize, true,
17 "If set, converage information will be symbolized by sancov tool "
18 "after dumping.")
19
20SANCOV_FLAG(bool, help, false, "Print flags help.")
lib/tsan/sanitizer_common/sanitizer_addrhashmap.h created+353
...@@ -0,0 +1,353 @@
1//===-- sanitizer_addrhashmap.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// Concurrent uptr->T hashmap.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef SANITIZER_ADDRHASHMAP_H
14#define SANITIZER_ADDRHASHMAP_H
15
16#include "sanitizer_common.h"
17#include "sanitizer_mutex.h"
18#include "sanitizer_atomic.h"
19#include "sanitizer_allocator_internal.h"
20
21namespace __sanitizer {
22
23// Concurrent uptr->T hashmap.
24// T must be a POD type, kSize is preferably a prime but can be any number.
25// Usage example:
26//
27// typedef AddrHashMap<uptr, 11> Map;
28// Map m;
29// {
30// Map::Handle h(&m, addr);
31// use h.operator->() to access the data
32// if h.created() then the element was just created, and the current thread
33// has exclusive access to it
34// otherwise the current thread has only read access to the data
35// }
36// {
37// Map::Handle h(&m, addr, true);
38// this will remove the data from the map in Handle dtor
39// the current thread has exclusive access to the data
40// if !h.exists() then the element never existed
41// }
42template<typename T, uptr kSize>
43class AddrHashMap {
44 private:
45 struct Cell {
46 atomic_uintptr_t addr;
47 T val;
48 };
49
50 struct AddBucket {
51 uptr cap;
52 uptr size;
53 Cell cells[1]; // variable len
54 };
55
56 static const uptr kBucketSize = 3;
57
58 struct Bucket {
59 RWMutex mtx;
60 atomic_uintptr_t add;
61 Cell cells[kBucketSize];
62 };
63
64 public:
65 AddrHashMap();
66
67 class Handle {
68 public:
69 Handle(AddrHashMap<T, kSize> *map, uptr addr);
70 Handle(AddrHashMap<T, kSize> *map, uptr addr, bool remove);
71 Handle(AddrHashMap<T, kSize> *map, uptr addr, bool remove, bool create);
72
73 ~Handle();
74 T *operator->();
75 T &operator*();
76 const T &operator*() const;
77 bool created() const;
78 bool exists() const;
79
80 private:
81 friend AddrHashMap<T, kSize>;
82 AddrHashMap<T, kSize> *map_;
83 Bucket *bucket_;
84 Cell *cell_;
85 uptr addr_;
86 uptr addidx_;
87 bool created_;
88 bool remove_;
89 bool create_;
90 };
91
92 private:
93 friend class Handle;
94 Bucket *table_;
95
96 void acquire(Handle *h);
97 void release(Handle *h);
98 uptr calcHash(uptr addr);
99};
100
101template<typename T, uptr kSize>
102AddrHashMap<T, kSize>::Handle::Handle(AddrHashMap<T, kSize> *map, uptr addr) {
103 map_ = map;
104 addr_ = addr;
105 remove_ = false;
106 create_ = true;
107 map_->acquire(this);
108}
109
110template<typename T, uptr kSize>
111AddrHashMap<T, kSize>::Handle::Handle(AddrHashMap<T, kSize> *map, uptr addr,
112 bool remove) {
113 map_ = map;
114 addr_ = addr;
115 remove_ = remove;
116 create_ = true;
117 map_->acquire(this);
118}
119
120template<typename T, uptr kSize>
121AddrHashMap<T, kSize>::Handle::Handle(AddrHashMap<T, kSize> *map, uptr addr,
122 bool remove, bool create) {
123 map_ = map;
124 addr_ = addr;
125 remove_ = remove;
126 create_ = create;
127 map_->acquire(this);
128}
129
130template<typename T, uptr kSize>
131AddrHashMap<T, kSize>::Handle::~Handle() {
132 map_->release(this);
133}
134
135template <typename T, uptr kSize>
136T *AddrHashMap<T, kSize>::Handle::operator->() {
137 return &cell_->val;
138}
139
140template <typename T, uptr kSize>
141const T &AddrHashMap<T, kSize>::Handle::operator*() const {
142 return cell_->val;
143}
144
145template <typename T, uptr kSize>
146T &AddrHashMap<T, kSize>::Handle::operator*() {
147 return cell_->val;
148}
149
150template<typename T, uptr kSize>
151bool AddrHashMap<T, kSize>::Handle::created() const {
152 return created_;
153}
154
155template<typename T, uptr kSize>
156bool AddrHashMap<T, kSize>::Handle::exists() const {
157 return cell_ != nullptr;
158}
159
160template<typename T, uptr kSize>
161AddrHashMap<T, kSize>::AddrHashMap() {
162 table_ = (Bucket*)MmapOrDie(kSize * sizeof(table_[0]), "AddrHashMap");
163}
164
165template<typename T, uptr kSize>
166void AddrHashMap<T, kSize>::acquire(Handle *h) {
167 uptr addr = h->addr_;
168 uptr hash = calcHash(addr);
169 Bucket *b = &table_[hash];
170
171 h->created_ = false;
172 h->addidx_ = -1U;
173 h->bucket_ = b;
174 h->cell_ = nullptr;
175
176 // If we want to remove the element, we need exclusive access to the bucket,
177 // so skip the lock-free phase.
178 if (h->remove_)
179 goto locked;
180
181 retry:
182 // First try to find an existing element w/o read mutex.
183 CHECK(!h->remove_);
184 // Check the embed cells.
185 for (uptr i = 0; i < kBucketSize; i++) {
186 Cell *c = &b->cells[i];
187 uptr addr1 = atomic_load(&c->addr, memory_order_acquire);
188 if (addr1 == addr) {
189 h->cell_ = c;
190 return;
191 }
192 }
193
194 // Check the add cells with read lock.
195 if (atomic_load(&b->add, memory_order_relaxed)) {
196 b->mtx.ReadLock();
197 AddBucket *add = (AddBucket*)atomic_load(&b->add, memory_order_relaxed);
198 for (uptr i = 0; i < add->size; i++) {
199 Cell *c = &add->cells[i];
200 uptr addr1 = atomic_load(&c->addr, memory_order_relaxed);
201 if (addr1 == addr) {
202 h->addidx_ = i;
203 h->cell_ = c;
204 return;
205 }
206 }
207 b->mtx.ReadUnlock();
208 }
209
210 locked:
211 // Re-check existence under write lock.
212 // Embed cells.
213 b->mtx.Lock();
214 for (uptr i = 0; i < kBucketSize; i++) {
215 Cell *c = &b->cells[i];
216 uptr addr1 = atomic_load(&c->addr, memory_order_relaxed);
217 if (addr1 == addr) {
218 if (h->remove_) {
219 h->cell_ = c;
220 return;
221 }
222 b->mtx.Unlock();
223 goto retry;
224 }
225 }
226
227 // Add cells.
228 AddBucket *add = (AddBucket*)atomic_load(&b->add, memory_order_relaxed);
229 if (add) {
230 for (uptr i = 0; i < add->size; i++) {
231 Cell *c = &add->cells[i];
232 uptr addr1 = atomic_load(&c->addr, memory_order_relaxed);
233 if (addr1 == addr) {
234 if (h->remove_) {
235 h->addidx_ = i;
236 h->cell_ = c;
237 return;
238 }
239 b->mtx.Unlock();
240 goto retry;
241 }
242 }
243 }
244
245 // The element does not exist, no need to create it if we want to remove.
246 if (h->remove_ || !h->create_) {
247 b->mtx.Unlock();
248 return;
249 }
250
251 // Now try to create it under the mutex.
252 h->created_ = true;
253 // See if we have a free embed cell.
254 for (uptr i = 0; i < kBucketSize; i++) {
255 Cell *c = &b->cells[i];
256 uptr addr1 = atomic_load(&c->addr, memory_order_relaxed);
257 if (addr1 == 0) {
258 h->cell_ = c;
259 return;
260 }
261 }
262
263 // Store in the add cells.
264 if (!add) {
265 // Allocate a new add array.
266 const uptr kInitSize = 64;
267 add = (AddBucket*)InternalAlloc(kInitSize);
268 internal_memset(add, 0, kInitSize);
269 add->cap = (kInitSize - sizeof(*add)) / sizeof(add->cells[0]) + 1;
270 add->size = 0;
271 atomic_store(&b->add, (uptr)add, memory_order_relaxed);
272 }
273 if (add->size == add->cap) {
274 // Grow existing add array.
275 uptr oldsize = sizeof(*add) + (add->cap - 1) * sizeof(add->cells[0]);
276 uptr newsize = oldsize * 2;
277 AddBucket *add1 = (AddBucket*)InternalAlloc(newsize);
278 internal_memset(add1, 0, newsize);
279 add1->cap = (newsize - sizeof(*add)) / sizeof(add->cells[0]) + 1;
280 add1->size = add->size;
281 internal_memcpy(add1->cells, add->cells, add->size * sizeof(add->cells[0]));
282 InternalFree(add);
283 atomic_store(&b->add, (uptr)add1, memory_order_relaxed);
284 add = add1;
285 }
286 // Store.
287 uptr i = add->size++;
288 Cell *c = &add->cells[i];
289 CHECK_EQ(atomic_load(&c->addr, memory_order_relaxed), 0);
290 h->addidx_ = i;
291 h->cell_ = c;
292}
293
294template<typename T, uptr kSize>
295void AddrHashMap<T, kSize>::release(Handle *h) {
296 if (!h->cell_)
297 return;
298 Bucket *b = h->bucket_;
299 Cell *c = h->cell_;
300 uptr addr1 = atomic_load(&c->addr, memory_order_relaxed);
301 if (h->created_) {
302 // Denote completion of insertion.
303 CHECK_EQ(addr1, 0);
304 // After the following store, the element becomes available
305 // for lock-free reads.
306 atomic_store(&c->addr, h->addr_, memory_order_release);
307 b->mtx.Unlock();
308 } else if (h->remove_) {
309 // Denote that the cell is empty now.
310 CHECK_EQ(addr1, h->addr_);
311 atomic_store(&c->addr, 0, memory_order_release);
312 // See if we need to compact the bucket.
313 AddBucket *add = (AddBucket*)atomic_load(&b->add, memory_order_relaxed);
314 if (h->addidx_ == -1U) {
315 // Removed from embed array, move an add element into the freed cell.
316 if (add && add->size != 0) {
317 uptr last = --add->size;
318 Cell *c1 = &add->cells[last];
319 c->val = c1->val;
320 uptr addr1 = atomic_load(&c1->addr, memory_order_relaxed);
321 atomic_store(&c->addr, addr1, memory_order_release);
322 atomic_store(&c1->addr, 0, memory_order_release);
323 }
324 } else {
325 // Removed from add array, compact it.
326 uptr last = --add->size;
327 Cell *c1 = &add->cells[last];
328 if (c != c1) {
329 *c = *c1;
330 atomic_store(&c1->addr, 0, memory_order_relaxed);
331 }
332 }
333 if (add && add->size == 0) {
334 // FIXME(dvyukov): free add?
335 }
336 b->mtx.Unlock();
337 } else {
338 CHECK_EQ(addr1, h->addr_);
339 if (h->addidx_ != -1U)
340 b->mtx.ReadUnlock();
341 }
342}
343
344template<typename T, uptr kSize>
345uptr AddrHashMap<T, kSize>::calcHash(uptr addr) {
346 addr += addr << 10;
347 addr ^= addr >> 6;
348 return addr % kSize;
349}
350
351} // namespace __sanitizer
352
353#endif // SANITIZER_ADDRHASHMAP_H
lib/tsan/sanitizer_common/sanitizer_allocator.cpp created+267
...@@ -0,0 +1,267 @@
1//===-- sanitizer_allocator.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 shared between AddressSanitizer and ThreadSanitizer
10// run-time libraries.
11// This allocator is used inside run-times.
12//===----------------------------------------------------------------------===//
13
14#include "sanitizer_allocator.h"
15
16#include "sanitizer_allocator_checks.h"
17#include "sanitizer_allocator_internal.h"
18#include "sanitizer_atomic.h"
19#include "sanitizer_common.h"
20
21namespace __sanitizer {
22
23// Default allocator names.
24const char *PrimaryAllocatorName = "SizeClassAllocator";
25const char *SecondaryAllocatorName = "LargeMmapAllocator";
26
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
87static ALIGNED(64) char internal_alloc_placeholder[sizeof(InternalAllocator)];
88static atomic_uint8_t internal_allocator_initialized;
89static StaticSpinMutex internal_alloc_init_mu;
90
91static InternalAllocatorCache internal_allocator_cache;
92static StaticSpinMutex internal_allocator_cache_mu;
93
94InternalAllocator *internal_allocator() {
95 InternalAllocator *internal_allocator_instance =
96 reinterpret_cast<InternalAllocator *>(&internal_alloc_placeholder);
97 if (atomic_load(&internal_allocator_initialized, memory_order_acquire) == 0) {
98 SpinMutexLock l(&internal_alloc_init_mu);
99 if (atomic_load(&internal_allocator_initialized, memory_order_relaxed) ==
100 0) {
101 internal_allocator_instance->Init(kReleaseToOSIntervalNever);
102 atomic_store(&internal_allocator_initialized, 1, memory_order_release);
103 }
104 }
105 return internal_allocator_instance;
106}
107
108static void *RawInternalAlloc(uptr size, InternalAllocatorCache *cache,
109 uptr alignment) {
110 if (alignment == 0) alignment = 8;
111 if (cache == 0) {
112 SpinMutexLock l(&internal_allocator_cache_mu);
113 return internal_allocator()->Allocate(&internal_allocator_cache, size,
114 alignment);
115 }
116 return internal_allocator()->Allocate(cache, size, alignment);
117}
118
119static void *RawInternalRealloc(void *ptr, uptr size,
120 InternalAllocatorCache *cache) {
121 uptr alignment = 8;
122 if (cache == 0) {
123 SpinMutexLock l(&internal_allocator_cache_mu);
124 return internal_allocator()->Reallocate(&internal_allocator_cache, ptr,
125 size, alignment);
126 }
127 return internal_allocator()->Reallocate(cache, ptr, size, alignment);
128}
129
130static void RawInternalFree(void *ptr, InternalAllocatorCache *cache) {
131 if (!cache) {
132 SpinMutexLock l(&internal_allocator_cache_mu);
133 return internal_allocator()->Deallocate(&internal_allocator_cache, ptr);
134 }
135 internal_allocator()->Deallocate(cache, ptr);
136}
137
138#endif // SANITIZER_GO || defined(SANITIZER_USE_MALLOC)
139
140const u64 kBlockMagic = 0x6A6CB03ABCEBC041ull;
141
142static void NORETURN ReportInternalAllocatorOutOfMemory(uptr requested_size) {
143 SetAllocatorOutOfMemory();
144 Report("FATAL: %s: internal allocator is out of memory trying to allocate "
145 "0x%zx bytes\n", SanitizerToolName, requested_size);
146 Die();
147}
148
149void *InternalAlloc(uptr size, InternalAllocatorCache *cache, uptr alignment) {
150 if (size + sizeof(u64) < size)
151 return nullptr;
152 void *p = RawInternalAlloc(size + sizeof(u64), cache, alignment);
153 if (UNLIKELY(!p))
154 ReportInternalAllocatorOutOfMemory(size + sizeof(u64));
155 ((u64*)p)[0] = kBlockMagic;
156 return (char*)p + sizeof(u64);
157}
158
159void *InternalRealloc(void *addr, uptr size, InternalAllocatorCache *cache) {
160 if (!addr)
161 return InternalAlloc(size, cache);
162 if (size + sizeof(u64) < size)
163 return nullptr;
164 addr = (char*)addr - sizeof(u64);
165 size = size + sizeof(u64);
166 CHECK_EQ(kBlockMagic, ((u64*)addr)[0]);
167 void *p = RawInternalRealloc(addr, size, cache);
168 if (UNLIKELY(!p))
169 ReportInternalAllocatorOutOfMemory(size);
170 return (char*)p + sizeof(u64);
171}
172
173void *InternalReallocArray(void *addr, uptr count, uptr size,
174 InternalAllocatorCache *cache) {
175 if (UNLIKELY(CheckForCallocOverflow(count, size))) {
176 Report(
177 "FATAL: %s: reallocarray parameters overflow: count * size (%zd * %zd) "
178 "cannot be represented in type size_t\n",
179 SanitizerToolName, count, size);
180 Die();
181 }
182 return InternalRealloc(addr, count * size, cache);
183}
184
185void *InternalCalloc(uptr count, uptr size, InternalAllocatorCache *cache) {
186 if (UNLIKELY(CheckForCallocOverflow(count, size))) {
187 Report("FATAL: %s: calloc parameters overflow: count * size (%zd * %zd) "
188 "cannot be represented in type size_t\n", SanitizerToolName, count,
189 size);
190 Die();
191 }
192 void *p = InternalAlloc(count * size, cache);
193 if (LIKELY(p))
194 internal_memset(p, 0, count * size);
195 return p;
196}
197
198void InternalFree(void *addr, InternalAllocatorCache *cache) {
199 if (!addr)
200 return;
201 addr = (char*)addr - sizeof(u64);
202 CHECK_EQ(kBlockMagic, ((u64*)addr)[0]);
203 ((u64*)addr)[0] = 0;
204 RawInternalFree(addr, cache);
205}
206
207// LowLevelAllocator
208constexpr uptr kLowLevelAllocatorDefaultAlignment = 8;
209static uptr low_level_alloc_min_alignment = kLowLevelAllocatorDefaultAlignment;
210static LowLevelAllocateCallback low_level_alloc_callback;
211
212void *LowLevelAllocator::Allocate(uptr size) {
213 // Align allocation size.
214 size = RoundUpTo(size, low_level_alloc_min_alignment);
215 if (allocated_end_ - allocated_current_ < (sptr)size) {
216 uptr size_to_allocate = RoundUpTo(size, GetPageSizeCached());
217 allocated_current_ =
218 (char*)MmapOrDie(size_to_allocate, __func__);
219 allocated_end_ = allocated_current_ + size_to_allocate;
220 if (low_level_alloc_callback) {
221 low_level_alloc_callback((uptr)allocated_current_,
222 size_to_allocate);
223 }
224 }
225 CHECK(allocated_end_ - allocated_current_ >= (sptr)size);
226 void *res = allocated_current_;
227 allocated_current_ += size;
228 return res;
229}
230
231void SetLowLevelAllocateMinAlignment(uptr alignment) {
232 CHECK(IsPowerOfTwo(alignment));
233 low_level_alloc_min_alignment = Max(alignment, low_level_alloc_min_alignment);
234}
235
236void SetLowLevelAllocateCallback(LowLevelAllocateCallback callback) {
237 low_level_alloc_callback = callback;
238}
239
240// Allocator's OOM and other errors handling support.
241
242static atomic_uint8_t allocator_out_of_memory = {0};
243static atomic_uint8_t allocator_may_return_null = {0};
244
245bool IsAllocatorOutOfMemory() {
246 return atomic_load_relaxed(&allocator_out_of_memory);
247}
248
249void SetAllocatorOutOfMemory() {
250 atomic_store_relaxed(&allocator_out_of_memory, 1);
251}
252
253bool AllocatorMayReturnNull() {
254 return atomic_load(&allocator_may_return_null, memory_order_relaxed);
255}
256
257void SetAllocatorMayReturnNull(bool may_return_null) {
258 atomic_store(&allocator_may_return_null, may_return_null,
259 memory_order_relaxed);
260}
261
262void PrintHintAllocatorCannotReturnNull() {
263 Report("HINT: if you don't care about these errors you may set "
264 "allocator_may_return_null=1\n");
265}
266
267} // namespace __sanitizer
lib/tsan/sanitizer_common/sanitizer_allocator.h created+81
...@@ -0,0 +1,81 @@
1//===-- sanitizer_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// Specialized memory allocator for ThreadSanitizer, MemorySanitizer, etc.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef SANITIZER_ALLOCATOR_H
14#define SANITIZER_ALLOCATOR_H
15
16#include "sanitizer_common.h"
17#include "sanitizer_internal_defs.h"
18#include "sanitizer_lfstack.h"
19#include "sanitizer_libc.h"
20#include "sanitizer_list.h"
21#include "sanitizer_local_address_space_view.h"
22#include "sanitizer_mutex.h"
23#include "sanitizer_procmaps.h"
24#include "sanitizer_type_traits.h"
25
26namespace __sanitizer {
27
28// Allows the tools to name their allocations appropriately.
29extern const char *PrimaryAllocatorName;
30extern const char *SecondaryAllocatorName;
31
32// Since flags are immutable and allocator behavior can be changed at runtime
33// (unit tests or ASan on Android are some examples), allocator_may_return_null
34// flag value is cached here and can be altered later.
35bool AllocatorMayReturnNull();
36void SetAllocatorMayReturnNull(bool may_return_null);
37
38// Returns true if allocator detected OOM condition. Can be used to avoid memory
39// hungry operations.
40bool IsAllocatorOutOfMemory();
41// Should be called by a particular allocator when OOM is detected.
42void SetAllocatorOutOfMemory();
43
44void PrintHintAllocatorCannotReturnNull();
45
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
52// Callback type for iterating over chunks.
53typedef void (*ForEachChunkCallback)(uptr chunk, void *arg);
54
55INLINE u32 Rand(u32 *state) { // ANSI C linear congruential PRNG.
56 return (*state = *state * 1103515245 + 12345) >> 16;
57}
58
59INLINE u32 RandN(u32 *state, u32 n) { return Rand(state) % n; } // [0, n)
60
61template<typename T>
62INLINE void RandomShuffle(T *a, u32 n, u32 *rand_state) {
63 if (n <= 1) return;
64 u32 state = *rand_state;
65 for (u32 i = n - 1; i > 0; i--)
66 Swap(a[i], a[RandN(&state, i + 1)]);
67 *rand_state = state;
68}
69
70#include "sanitizer_allocator_size_class_map.h"
71#include "sanitizer_allocator_stats.h"
72#include "sanitizer_allocator_primary64.h"
73#include "sanitizer_allocator_bytemap.h"
74#include "sanitizer_allocator_primary32.h"
75#include "sanitizer_allocator_local_cache.h"
76#include "sanitizer_allocator_secondary.h"
77#include "sanitizer_allocator_combined.h"
78
79} // namespace __sanitizer
80
81#endif // SANITIZER_ALLOCATOR_H
lib/tsan/sanitizer_common/sanitizer_allocator_bytemap.h created+107
...@@ -0,0 +1,107 @@
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_checks.h created+76
...@@ -0,0 +1,76 @@
1//===-- sanitizer_allocator_checks.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// Various checks shared between ThreadSanitizer, MemorySanitizer, etc. memory
10// allocators.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef SANITIZER_ALLOCATOR_CHECKS_H
15#define SANITIZER_ALLOCATOR_CHECKS_H
16
17#include "sanitizer_internal_defs.h"
18#include "sanitizer_common.h"
19#include "sanitizer_platform.h"
20
21namespace __sanitizer {
22
23// The following is defined in a separate compilation unit to avoid pulling in
24// sanitizer_errno.h in this header, which leads to conflicts when other system
25// headers include errno.h. This is usually the result of an unlikely event,
26// and as such we do not care as much about having it inlined.
27void SetErrnoToENOMEM();
28
29// A common errno setting logic shared by almost all sanitizer allocator APIs.
30INLINE void *SetErrnoOnNull(void *ptr) {
31 if (UNLIKELY(!ptr))
32 SetErrnoToENOMEM();
33 return ptr;
34}
35
36// In case of the check failure, the caller of the following Check... functions
37// should "return POLICY::OnBadRequest();" where POLICY is the current allocator
38// failure handling policy.
39
40// Checks aligned_alloc() parameters, verifies that the alignment is a power of
41// two and that the size is a multiple of alignment for POSIX implementation,
42// and a bit relaxed requirement for non-POSIX ones, that the size is a multiple
43// of alignment.
44INLINE bool CheckAlignedAllocAlignmentAndSize(uptr alignment, uptr size) {
45#if SANITIZER_POSIX
46 return alignment != 0 && IsPowerOfTwo(alignment) &&
47 (size & (alignment - 1)) == 0;
48#else
49 return alignment != 0 && size % alignment == 0;
50#endif
51}
52
53// Checks posix_memalign() parameters, verifies that alignment is a power of two
54// and a multiple of sizeof(void *).
55INLINE bool CheckPosixMemalignAlignment(uptr alignment) {
56 return alignment != 0 && IsPowerOfTwo(alignment) &&
57 (alignment % sizeof(void *)) == 0;
58}
59
60// Returns true if calloc(size, n) call overflows on size*n calculation.
61INLINE bool CheckForCallocOverflow(uptr size, uptr n) {
62 if (!size)
63 return false;
64 uptr max = (uptr)-1L;
65 return (max / size) < n;
66}
67
68// Returns true if the size passed to pvalloc overflows when rounded to the next
69// multiple of page_size.
70INLINE bool CheckForPvallocOverflow(uptr size, uptr page_size) {
71 return RoundUpTo(size, page_size) < size;
72}
73
74} // namespace __sanitizer
75
76#endif // SANITIZER_ALLOCATOR_CHECKS_H
lib/tsan/sanitizer_common/sanitizer_allocator_combined.h created+201
...@@ -0,0 +1,201 @@
1//===-- sanitizer_allocator_combined.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// This class implements a complete memory allocator by using two
17// internal allocators:
18// PrimaryAllocator is efficient, but may not allocate some sizes (alignments).
19// When allocating 2^x bytes it should return 2^x aligned chunk.
20// PrimaryAllocator is used via a local AllocatorCache.
21// SecondaryAllocator can allocate anything, but is not efficient.
22template <class PrimaryAllocator,
23 class LargeMmapAllocatorPtrArray = DefaultLargeMmapAllocatorPtrArray>
24class CombinedAllocator {
25 public:
26 using AllocatorCache = typename PrimaryAllocator::AllocatorCache;
27 using SecondaryAllocator =
28 LargeMmapAllocator<typename PrimaryAllocator::MapUnmapCallback,
29 LargeMmapAllocatorPtrArray,
30 typename PrimaryAllocator::AddressSpaceView>;
31
32 void InitLinkerInitialized(s32 release_to_os_interval_ms) {
33 stats_.InitLinkerInitialized();
34 primary_.Init(release_to_os_interval_ms);
35 secondary_.InitLinkerInitialized();
36 }
37
38 void Init(s32 release_to_os_interval_ms) {
39 stats_.Init();
40 primary_.Init(release_to_os_interval_ms);
41 secondary_.Init();
42 }
43
44 void *Allocate(AllocatorCache *cache, uptr size, uptr alignment) {
45 // Returning 0 on malloc(0) may break a lot of code.
46 if (size == 0)
47 size = 1;
48 if (size + alignment < size) {
49 Report("WARNING: %s: CombinedAllocator allocation overflow: "
50 "0x%zx bytes with 0x%zx alignment requested\n",
51 SanitizerToolName, size, alignment);
52 return nullptr;
53 }
54 uptr original_size = size;
55 // If alignment requirements are to be fulfilled by the frontend allocator
56 // rather than by the primary or secondary, passing an alignment lower than
57 // or equal to 8 will prevent any further rounding up, as well as the later
58 // alignment check.
59 if (alignment > 8)
60 size = RoundUpTo(size, alignment);
61 // The primary allocator should return a 2^x aligned allocation when
62 // requested 2^x bytes, hence using the rounded up 'size' when being
63 // serviced by the primary (this is no longer true when the primary is
64 // using a non-fixed base address). The secondary takes care of the
65 // alignment without such requirement, and allocating 'size' would use
66 // extraneous memory, so we employ 'original_size'.
67 void *res;
68 if (primary_.CanAllocate(size, alignment))
69 res = cache->Allocate(&primary_, primary_.ClassID(size));
70 else
71 res = secondary_.Allocate(&stats_, original_size, alignment);
72 if (alignment > 8)
73 CHECK_EQ(reinterpret_cast<uptr>(res) & (alignment - 1), 0);
74 return res;
75 }
76
77 s32 ReleaseToOSIntervalMs() const {
78 return primary_.ReleaseToOSIntervalMs();
79 }
80
81 void SetReleaseToOSIntervalMs(s32 release_to_os_interval_ms) {
82 primary_.SetReleaseToOSIntervalMs(release_to_os_interval_ms);
83 }
84
85 void ForceReleaseToOS() {
86 primary_.ForceReleaseToOS();
87 }
88
89 void Deallocate(AllocatorCache *cache, void *p) {
90 if (!p) return;
91 if (primary_.PointerIsMine(p))
92 cache->Deallocate(&primary_, primary_.GetSizeClass(p), p);
93 else
94 secondary_.Deallocate(&stats_, p);
95 }
96
97 void *Reallocate(AllocatorCache *cache, void *p, uptr new_size,
98 uptr alignment) {
99 if (!p)
100 return Allocate(cache, new_size, alignment);
101 if (!new_size) {
102 Deallocate(cache, p);
103 return nullptr;
104 }
105 CHECK(PointerIsMine(p));
106 uptr old_size = GetActuallyAllocatedSize(p);
107 uptr memcpy_size = Min(new_size, old_size);
108 void *new_p = Allocate(cache, new_size, alignment);
109 if (new_p)
110 internal_memcpy(new_p, p, memcpy_size);
111 Deallocate(cache, p);
112 return new_p;
113 }
114
115 bool PointerIsMine(void *p) {
116 if (primary_.PointerIsMine(p))
117 return true;
118 return secondary_.PointerIsMine(p);
119 }
120
121 bool FromPrimary(void *p) {
122 return primary_.PointerIsMine(p);
123 }
124
125 void *GetMetaData(const void *p) {
126 if (primary_.PointerIsMine(p))
127 return primary_.GetMetaData(p);
128 return secondary_.GetMetaData(p);
129 }
130
131 void *GetBlockBegin(const void *p) {
132 if (primary_.PointerIsMine(p))
133 return primary_.GetBlockBegin(p);
134 return secondary_.GetBlockBegin(p);
135 }
136
137 // This function does the same as GetBlockBegin, but is much faster.
138 // Must be called with the allocator locked.
139 void *GetBlockBeginFastLocked(void *p) {
140 if (primary_.PointerIsMine(p))
141 return primary_.GetBlockBegin(p);
142 return secondary_.GetBlockBeginFastLocked(p);
143 }
144
145 uptr GetActuallyAllocatedSize(void *p) {
146 if (primary_.PointerIsMine(p))
147 return primary_.GetActuallyAllocatedSize(p);
148 return secondary_.GetActuallyAllocatedSize(p);
149 }
150
151 uptr TotalMemoryUsed() {
152 return primary_.TotalMemoryUsed() + secondary_.TotalMemoryUsed();
153 }
154
155 void TestOnlyUnmap() { primary_.TestOnlyUnmap(); }
156
157 void InitCache(AllocatorCache *cache) {
158 cache->Init(&stats_);
159 }
160
161 void DestroyCache(AllocatorCache *cache) {
162 cache->Destroy(&primary_, &stats_);
163 }
164
165 void SwallowCache(AllocatorCache *cache) {
166 cache->Drain(&primary_);
167 }
168
169 void GetStats(AllocatorStatCounters s) const {
170 stats_.Get(s);
171 }
172
173 void PrintStats() {
174 primary_.PrintStats();
175 secondary_.PrintStats();
176 }
177
178 // ForceLock() and ForceUnlock() are needed to implement Darwin malloc zone
179 // introspection API.
180 void ForceLock() {
181 primary_.ForceLock();
182 secondary_.ForceLock();
183 }
184
185 void ForceUnlock() {
186 secondary_.ForceUnlock();
187 primary_.ForceUnlock();
188 }
189
190 // Iterate over all existing chunks.
191 // The allocator must be locked when calling this function.
192 void ForEachChunk(ForEachChunkCallback callback, void *arg) {
193 primary_.ForEachChunk(callback, arg);
194 secondary_.ForEachChunk(callback, arg);
195 }
196
197 private:
198 PrimaryAllocator primary_;
199 SecondaryAllocator secondary_;
200 AllocatorGlobalStats stats_;
201};
lib/tsan/sanitizer_common/sanitizer_allocator_interface.h created+47
...@@ -0,0 +1,47 @@
1//===-- sanitizer_allocator_interface.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// Re-declaration of functions from public sanitizer allocator interface.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef SANITIZER_ALLOCATOR_INTERFACE_H
14#define SANITIZER_ALLOCATOR_INTERFACE_H
15
16#include "sanitizer_internal_defs.h"
17
18using __sanitizer::uptr;
19
20extern "C" {
21SANITIZER_INTERFACE_ATTRIBUTE
22uptr __sanitizer_get_estimated_allocated_size(uptr size);
23SANITIZER_INTERFACE_ATTRIBUTE int __sanitizer_get_ownership(const void *p);
24SANITIZER_INTERFACE_ATTRIBUTE uptr
25__sanitizer_get_allocated_size(const void *p);
26SANITIZER_INTERFACE_ATTRIBUTE uptr __sanitizer_get_current_allocated_bytes();
27SANITIZER_INTERFACE_ATTRIBUTE uptr __sanitizer_get_heap_size();
28SANITIZER_INTERFACE_ATTRIBUTE uptr __sanitizer_get_free_bytes();
29SANITIZER_INTERFACE_ATTRIBUTE uptr __sanitizer_get_unmapped_bytes();
30
31SANITIZER_INTERFACE_ATTRIBUTE int __sanitizer_install_malloc_and_free_hooks(
32 void (*malloc_hook)(const void *, uptr),
33 void (*free_hook)(const void *));
34
35SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
36 void __sanitizer_malloc_hook(void *ptr, uptr size);
37SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
38 void __sanitizer_free_hook(void *ptr);
39
40SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
41__sanitizer_purge_allocator();
42
43SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
44__sanitizer_print_memory_profile(uptr top_percent, uptr max_number_of_contexts);
45} // extern "C"
46
47#endif // SANITIZER_ALLOCATOR_INTERFACE_H
lib/tsan/sanitizer_common/sanitizer_allocator_internal.h created+55
...@@ -0,0 +1,55 @@
1//===-- sanitizer_allocator_internal.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 allocator is used inside run-times.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef SANITIZER_ALLOCATOR_INTERNAL_H
14#define SANITIZER_ALLOCATOR_INTERNAL_H
15
16#include "sanitizer_allocator.h"
17#include "sanitizer_internal_defs.h"
18
19namespace __sanitizer {
20
21// FIXME: Check if we may use even more compact size class map for internal
22// purposes.
23typedef CompactSizeClassMap InternalSizeClassMap;
24
25struct AP32 {
26 static const uptr kSpaceBeg = 0;
27 static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE;
28 static const uptr kMetadataSize = 0;
29 typedef InternalSizeClassMap SizeClassMap;
30 static const uptr kRegionSizeLog = 20;
31 using AddressSpaceView = LocalAddressSpaceView;
32 typedef NoOpMapUnmapCallback MapUnmapCallback;
33 static const uptr kFlags = 0;
34};
35typedef SizeClassAllocator32<AP32> PrimaryInternalAllocator;
36
37typedef CombinedAllocator<PrimaryInternalAllocator,
38 LargeMmapAllocatorPtrArrayStatic>
39 InternalAllocator;
40typedef InternalAllocator::AllocatorCache InternalAllocatorCache;
41
42void *InternalAlloc(uptr size, InternalAllocatorCache *cache = nullptr,
43 uptr alignment = 0);
44void *InternalRealloc(void *p, uptr size,
45 InternalAllocatorCache *cache = nullptr);
46void *InternalReallocArray(void *p, uptr count, uptr size,
47 InternalAllocatorCache *cache = nullptr);
48void *InternalCalloc(uptr count, uptr size,
49 InternalAllocatorCache *cache = nullptr);
50void InternalFree(void *p, InternalAllocatorCache *cache = nullptr);
51InternalAllocator *internal_allocator();
52
53} // namespace __sanitizer
54
55#endif // SANITIZER_ALLOCATOR_INTERNAL_H
lib/tsan/sanitizer_common/sanitizer_allocator_local_cache.h created+264
...@@ -0,0 +1,264 @@
1//===-- sanitizer_allocator_local_cache.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// Cache used by SizeClassAllocator64.
17template <class SizeClassAllocator>
18struct SizeClassAllocator64LocalCache {
19 typedef SizeClassAllocator Allocator;
20
21 void Init(AllocatorGlobalStats *s) {
22 stats_.Init();
23 if (s)
24 s->Register(&stats_);
25 }
26
27 void Destroy(SizeClassAllocator *allocator, AllocatorGlobalStats *s) {
28 Drain(allocator);
29 if (s)
30 s->Unregister(&stats_);
31 }
32
33 void *Allocate(SizeClassAllocator *allocator, uptr class_id) {
34 CHECK_NE(class_id, 0UL);
35 CHECK_LT(class_id, kNumClasses);
36 PerClass *c = &per_class_[class_id];
37 if (UNLIKELY(c->count == 0)) {
38 if (UNLIKELY(!Refill(c, allocator, class_id)))
39 return nullptr;
40 DCHECK_GT(c->count, 0);
41 }
42 CompactPtrT chunk = c->chunks[--c->count];
43 stats_.Add(AllocatorStatAllocated, c->class_size);
44 return reinterpret_cast<void *>(allocator->CompactPtrToPointer(
45 allocator->GetRegionBeginBySizeClass(class_id), chunk));
46 }
47
48 void Deallocate(SizeClassAllocator *allocator, uptr class_id, void *p) {
49 CHECK_NE(class_id, 0UL);
50 CHECK_LT(class_id, kNumClasses);
51 // If the first allocator call on a new thread is a deallocation, then
52 // max_count will be zero, leading to check failure.
53 PerClass *c = &per_class_[class_id];
54 InitCache(c);
55 if (UNLIKELY(c->count == c->max_count))
56 Drain(c, allocator, class_id, c->max_count / 2);
57 CompactPtrT chunk = allocator->PointerToCompactPtr(
58 allocator->GetRegionBeginBySizeClass(class_id),
59 reinterpret_cast<uptr>(p));
60 c->chunks[c->count++] = chunk;
61 stats_.Sub(AllocatorStatAllocated, c->class_size);
62 }
63
64 void Drain(SizeClassAllocator *allocator) {
65 for (uptr i = 1; i < kNumClasses; i++) {
66 PerClass *c = &per_class_[i];
67 while (c->count > 0)
68 Drain(c, allocator, i, c->count);
69 }
70 }
71
72 private:
73 typedef typename Allocator::SizeClassMapT SizeClassMap;
74 static const uptr kNumClasses = SizeClassMap::kNumClasses;
75 typedef typename Allocator::CompactPtrT CompactPtrT;
76
77 struct PerClass {
78 u32 count;
79 u32 max_count;
80 uptr class_size;
81 CompactPtrT chunks[2 * SizeClassMap::kMaxNumCachedHint];
82 };
83 PerClass per_class_[kNumClasses];
84 AllocatorStats stats_;
85
86 void InitCache(PerClass *c) {
87 if (LIKELY(c->max_count))
88 return;
89 for (uptr i = 1; i < kNumClasses; i++) {
90 PerClass *c = &per_class_[i];
91 const uptr size = Allocator::ClassIdToSize(i);
92 c->max_count = 2 * SizeClassMap::MaxCachedHint(size);
93 c->class_size = size;
94 }
95 DCHECK_NE(c->max_count, 0UL);
96 }
97
98 NOINLINE bool Refill(PerClass *c, SizeClassAllocator *allocator,
99 uptr class_id) {
100 InitCache(c);
101 const uptr num_requested_chunks = c->max_count / 2;
102 if (UNLIKELY(!allocator->GetFromAllocator(&stats_, class_id, c->chunks,
103 num_requested_chunks)))
104 return false;
105 c->count = num_requested_chunks;
106 return true;
107 }
108
109 NOINLINE void Drain(PerClass *c, SizeClassAllocator *allocator, uptr class_id,
110 uptr count) {
111 CHECK_GE(c->count, count);
112 const uptr first_idx_to_drain = c->count - count;
113 c->count -= count;
114 allocator->ReturnToAllocator(&stats_, class_id,
115 &c->chunks[first_idx_to_drain], count);
116 }
117};
118
119// Cache used by SizeClassAllocator32.
120template <class SizeClassAllocator>
121struct SizeClassAllocator32LocalCache {
122 typedef SizeClassAllocator Allocator;
123 typedef typename Allocator::TransferBatch TransferBatch;
124
125 void Init(AllocatorGlobalStats *s) {
126 stats_.Init();
127 if (s)
128 s->Register(&stats_);
129 }
130
131 // Returns a TransferBatch suitable for class_id.
132 TransferBatch *CreateBatch(uptr class_id, SizeClassAllocator *allocator,
133 TransferBatch *b) {
134 if (uptr batch_class_id = per_class_[class_id].batch_class_id)
135 return (TransferBatch*)Allocate(allocator, batch_class_id);
136 return b;
137 }
138
139 // Destroys TransferBatch b.
140 void DestroyBatch(uptr class_id, SizeClassAllocator *allocator,
141 TransferBatch *b) {
142 if (uptr batch_class_id = per_class_[class_id].batch_class_id)
143 Deallocate(allocator, batch_class_id, b);
144 }
145
146 void Destroy(SizeClassAllocator *allocator, AllocatorGlobalStats *s) {
147 Drain(allocator);
148 if (s)
149 s->Unregister(&stats_);
150 }
151
152 void *Allocate(SizeClassAllocator *allocator, uptr class_id) {
153 CHECK_NE(class_id, 0UL);
154 CHECK_LT(class_id, kNumClasses);
155 PerClass *c = &per_class_[class_id];
156 if (UNLIKELY(c->count == 0)) {
157 if (UNLIKELY(!Refill(c, allocator, class_id)))
158 return nullptr;
159 DCHECK_GT(c->count, 0);
160 }
161 void *res = c->batch[--c->count];
162 PREFETCH(c->batch[c->count - 1]);
163 stats_.Add(AllocatorStatAllocated, c->class_size);
164 return res;
165 }
166
167 void Deallocate(SizeClassAllocator *allocator, uptr class_id, void *p) {
168 CHECK_NE(class_id, 0UL);
169 CHECK_LT(class_id, kNumClasses);
170 // If the first allocator call on a new thread is a deallocation, then
171 // max_count will be zero, leading to check failure.
172 PerClass *c = &per_class_[class_id];
173 InitCache(c);
174 if (UNLIKELY(c->count == c->max_count))
175 Drain(c, allocator, class_id);
176 c->batch[c->count++] = p;
177 stats_.Sub(AllocatorStatAllocated, c->class_size);
178 }
179
180 void Drain(SizeClassAllocator *allocator) {
181 for (uptr i = 1; i < kNumClasses; i++) {
182 PerClass *c = &per_class_[i];
183 while (c->count > 0)
184 Drain(c, allocator, i);
185 }
186 }
187
188 private:
189 typedef typename Allocator::SizeClassMapT SizeClassMap;
190 static const uptr kBatchClassID = SizeClassMap::kBatchClassID;
191 static const uptr kNumClasses = SizeClassMap::kNumClasses;
192 // If kUseSeparateSizeClassForBatch is true, all TransferBatch objects are
193 // allocated from kBatchClassID size class (except for those that are needed
194 // for kBatchClassID itself). The goal is to have TransferBatches in a totally
195 // different region of RAM to improve security.
196 static const bool kUseSeparateSizeClassForBatch =
197 Allocator::kUseSeparateSizeClassForBatch;
198
199 struct PerClass {
200 uptr count;
201 uptr max_count;
202 uptr class_size;
203 uptr batch_class_id;
204 void *batch[2 * TransferBatch::kMaxNumCached];
205 };
206 PerClass per_class_[kNumClasses];
207 AllocatorStats stats_;
208
209 void InitCache(PerClass *c) {
210 if (LIKELY(c->max_count))
211 return;
212 const uptr batch_class_id = SizeClassMap::ClassID(sizeof(TransferBatch));
213 for (uptr i = 1; i < kNumClasses; i++) {
214 PerClass *c = &per_class_[i];
215 const uptr size = Allocator::ClassIdToSize(i);
216 const uptr max_cached = TransferBatch::MaxCached(size);
217 c->max_count = 2 * max_cached;
218 c->class_size = size;
219 // Precompute the class id to use to store batches for the current class
220 // id. 0 means the class size is large enough to store a batch within one
221 // of the chunks. If using a separate size class, it will always be
222 // kBatchClassID, except for kBatchClassID itself.
223 if (kUseSeparateSizeClassForBatch) {
224 c->batch_class_id = (i == kBatchClassID) ? 0 : kBatchClassID;
225 } else {
226 c->batch_class_id = (size <
227 TransferBatch::AllocationSizeRequiredForNElements(max_cached)) ?
228 batch_class_id : 0;
229 }
230 }
231 DCHECK_NE(c->max_count, 0UL);
232 }
233
234 NOINLINE bool Refill(PerClass *c, SizeClassAllocator *allocator,
235 uptr class_id) {
236 InitCache(c);
237 TransferBatch *b = allocator->AllocateBatch(&stats_, this, class_id);
238 if (UNLIKELY(!b))
239 return false;
240 CHECK_GT(b->Count(), 0);
241 b->CopyToArray(c->batch);
242 c->count = b->Count();
243 DestroyBatch(class_id, allocator, b);
244 return true;
245 }
246
247 NOINLINE void Drain(PerClass *c, SizeClassAllocator *allocator,
248 uptr class_id) {
249 const uptr count = Min(c->max_count / 2, c->count);
250 const uptr first_idx_to_drain = c->count - count;
251 TransferBatch *b = CreateBatch(
252 class_id, allocator, (TransferBatch *)c->batch[first_idx_to_drain]);
253 // Failure to allocate a batch while releasing memory is non recoverable.
254 // TODO(alekseys): Figure out how to do it without allocating a new batch.
255 if (UNLIKELY(!b)) {
256 Report("FATAL: Internal error: %s's allocator failed to allocate a "
257 "transfer batch.\n", SanitizerToolName);
258 Die();
259 }
260 b->SetFromArray(&c->batch[first_idx_to_drain], count);
261 c->count -= count;
262 allocator->DeallocateBatch(&stats_, class_id, b);
263 }
264};
lib/tsan/sanitizer_common/sanitizer_allocator_primary32.h created+380
...@@ -0,0 +1,380 @@
1//===-- sanitizer_allocator_primary32.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
16template<class SizeClassAllocator> struct SizeClassAllocator32LocalCache;
17
18// SizeClassAllocator32 -- allocator for 32-bit address space.
19// This allocator can theoretically be used on 64-bit arch, but there it is less
20// efficient than SizeClassAllocator64.
21//
22// [kSpaceBeg, kSpaceBeg + kSpaceSize) is the range of addresses which can
23// be returned by MmapOrDie().
24//
25// Region:
26// a result of a single call to MmapAlignedOrDieOnFatalError(kRegionSize,
27// kRegionSize).
28// Since the regions are aligned by kRegionSize, there are exactly
29// kNumPossibleRegions possible regions in the address space and so we keep
30// a ByteMap possible_regions to store the size classes of each Region.
31// 0 size class means the region is not used by the allocator.
32//
33// One Region is used to allocate chunks of a single size class.
34// A Region looks like this:
35// UserChunk1 .. UserChunkN <gap> MetaChunkN .. MetaChunk1
36//
37// In order to avoid false sharing the objects of this class should be
38// chache-line aligned.
39
40struct SizeClassAllocator32FlagMasks { // Bit masks.
41 enum {
42 kRandomShuffleChunks = 1,
43 kUseSeparateSizeClassForBatch = 2,
44 };
45};
46
47template <class Params>
48class SizeClassAllocator32 {
49 private:
50 static const u64 kTwoLevelByteMapSize1 =
51 (Params::kSpaceSize >> Params::kRegionSizeLog) >> 12;
52 static const u64 kMinFirstMapSizeTwoLevelByteMap = 4;
53
54 public:
55 using AddressSpaceView = typename Params::AddressSpaceView;
56 static const uptr kSpaceBeg = Params::kSpaceBeg;
57 static const u64 kSpaceSize = Params::kSpaceSize;
58 static const uptr kMetadataSize = Params::kMetadataSize;
59 typedef typename Params::SizeClassMap SizeClassMap;
60 static const uptr kRegionSizeLog = Params::kRegionSizeLog;
61 typedef typename Params::MapUnmapCallback MapUnmapCallback;
62 using ByteMap = typename conditional<
63 (kTwoLevelByteMapSize1 < kMinFirstMapSizeTwoLevelByteMap),
64 FlatByteMap<(Params::kSpaceSize >> Params::kRegionSizeLog),
65 AddressSpaceView>,
66 TwoLevelByteMap<kTwoLevelByteMapSize1, 1 << 12, AddressSpaceView>>::type;
67
68 COMPILER_CHECK(!SANITIZER_SIGN_EXTENDED_ADDRESSES ||
69 (kSpaceSize & (kSpaceSize - 1)) == 0);
70
71 static const bool kRandomShuffleChunks = Params::kFlags &
72 SizeClassAllocator32FlagMasks::kRandomShuffleChunks;
73 static const bool kUseSeparateSizeClassForBatch = Params::kFlags &
74 SizeClassAllocator32FlagMasks::kUseSeparateSizeClassForBatch;
75
76 struct TransferBatch {
77 static const uptr kMaxNumCached = SizeClassMap::kMaxNumCachedHint - 2;
78 void SetFromArray(void *batch[], uptr count) {
79 DCHECK_LE(count, kMaxNumCached);
80 count_ = count;
81 for (uptr i = 0; i < count; i++)
82 batch_[i] = batch[i];
83 }
84 uptr Count() const { return count_; }
85 void Clear() { count_ = 0; }
86 void Add(void *ptr) {
87 batch_[count_++] = ptr;
88 DCHECK_LE(count_, kMaxNumCached);
89 }
90 void CopyToArray(void *to_batch[]) const {
91 for (uptr i = 0, n = Count(); i < n; i++)
92 to_batch[i] = batch_[i];
93 }
94
95 // How much memory do we need for a batch containing n elements.
96 static uptr AllocationSizeRequiredForNElements(uptr n) {
97 return sizeof(uptr) * 2 + sizeof(void *) * n;
98 }
99 static uptr MaxCached(uptr size) {
100 return Min(kMaxNumCached, SizeClassMap::MaxCachedHint(size));
101 }
102
103 TransferBatch *next;
104
105 private:
106 uptr count_;
107 void *batch_[kMaxNumCached];
108 };
109
110 static const uptr kBatchSize = sizeof(TransferBatch);
111 COMPILER_CHECK((kBatchSize & (kBatchSize - 1)) == 0);
112 COMPILER_CHECK(kBatchSize == SizeClassMap::kMaxNumCachedHint * sizeof(uptr));
113
114 static uptr ClassIdToSize(uptr class_id) {
115 return (class_id == SizeClassMap::kBatchClassID) ?
116 kBatchSize : SizeClassMap::Size(class_id);
117 }
118
119 typedef SizeClassAllocator32<Params> ThisT;
120 typedef SizeClassAllocator32LocalCache<ThisT> AllocatorCache;
121
122 void Init(s32 release_to_os_interval_ms) {
123 possible_regions.Init();
124 internal_memset(size_class_info_array, 0, sizeof(size_class_info_array));
125 }
126
127 s32 ReleaseToOSIntervalMs() const {
128 return kReleaseToOSIntervalNever;
129 }
130
131 void SetReleaseToOSIntervalMs(s32 release_to_os_interval_ms) {
132 // This is empty here. Currently only implemented in 64-bit allocator.
133 }
134
135 void ForceReleaseToOS() {
136 // Currently implemented in 64-bit allocator only.
137 }
138
139 void *MapWithCallback(uptr size) {
140 void *res = MmapOrDie(size, PrimaryAllocatorName);
141 MapUnmapCallback().OnMap((uptr)res, size);
142 return res;
143 }
144
145 void UnmapWithCallback(uptr beg, uptr size) {
146 MapUnmapCallback().OnUnmap(beg, size);
147 UnmapOrDie(reinterpret_cast<void *>(beg), size);
148 }
149
150 static bool CanAllocate(uptr size, uptr alignment) {
151 return size <= SizeClassMap::kMaxSize &&
152 alignment <= SizeClassMap::kMaxSize;
153 }
154
155 void *GetMetaData(const void *p) {
156 CHECK(PointerIsMine(p));
157 uptr mem = reinterpret_cast<uptr>(p);
158 uptr beg = ComputeRegionBeg(mem);
159 uptr size = ClassIdToSize(GetSizeClass(p));
160 u32 offset = mem - beg;
161 uptr n = offset / (u32)size; // 32-bit division
162 uptr meta = (beg + kRegionSize) - (n + 1) * kMetadataSize;
163 return reinterpret_cast<void*>(meta);
164 }
165
166 NOINLINE TransferBatch *AllocateBatch(AllocatorStats *stat, AllocatorCache *c,
167 uptr class_id) {
168 DCHECK_LT(class_id, kNumClasses);
169 SizeClassInfo *sci = GetSizeClassInfo(class_id);
170 SpinMutexLock l(&sci->mutex);
171 if (sci->free_list.empty()) {
172 if (UNLIKELY(!PopulateFreeList(stat, c, sci, class_id)))
173 return nullptr;
174 DCHECK(!sci->free_list.empty());
175 }
176 TransferBatch *b = sci->free_list.front();
177 sci->free_list.pop_front();
178 return b;
179 }
180
181 NOINLINE void DeallocateBatch(AllocatorStats *stat, uptr class_id,
182 TransferBatch *b) {
183 DCHECK_LT(class_id, kNumClasses);
184 CHECK_GT(b->Count(), 0);
185 SizeClassInfo *sci = GetSizeClassInfo(class_id);
186 SpinMutexLock l(&sci->mutex);
187 sci->free_list.push_front(b);
188 }
189
190 bool PointerIsMine(const void *p) {
191 uptr mem = reinterpret_cast<uptr>(p);
192 if (SANITIZER_SIGN_EXTENDED_ADDRESSES)
193 mem &= (kSpaceSize - 1);
194 if (mem < kSpaceBeg || mem >= kSpaceBeg + kSpaceSize)
195 return false;
196 return GetSizeClass(p) != 0;
197 }
198
199 uptr GetSizeClass(const void *p) {
200 return possible_regions[ComputeRegionId(reinterpret_cast<uptr>(p))];
201 }
202
203 void *GetBlockBegin(const void *p) {
204 CHECK(PointerIsMine(p));
205 uptr mem = reinterpret_cast<uptr>(p);
206 uptr beg = ComputeRegionBeg(mem);
207 uptr size = ClassIdToSize(GetSizeClass(p));
208 u32 offset = mem - beg;
209 u32 n = offset / (u32)size; // 32-bit division
210 uptr res = beg + (n * (u32)size);
211 return reinterpret_cast<void*>(res);
212 }
213
214 uptr GetActuallyAllocatedSize(void *p) {
215 CHECK(PointerIsMine(p));
216 return ClassIdToSize(GetSizeClass(p));
217 }
218
219 static uptr ClassID(uptr size) { return SizeClassMap::ClassID(size); }
220
221 uptr TotalMemoryUsed() {
222 // No need to lock here.
223 uptr res = 0;
224 for (uptr i = 0; i < kNumPossibleRegions; i++)
225 if (possible_regions[i])
226 res += kRegionSize;
227 return res;
228 }
229
230 void TestOnlyUnmap() {
231 for (uptr i = 0; i < kNumPossibleRegions; i++)
232 if (possible_regions[i])
233 UnmapWithCallback((i * kRegionSize), kRegionSize);
234 }
235
236 // ForceLock() and ForceUnlock() are needed to implement Darwin malloc zone
237 // introspection API.
238 void ForceLock() {
239 for (uptr i = 0; i < kNumClasses; i++) {
240 GetSizeClassInfo(i)->mutex.Lock();
241 }
242 }
243
244 void ForceUnlock() {
245 for (int i = kNumClasses - 1; i >= 0; i--) {
246 GetSizeClassInfo(i)->mutex.Unlock();
247 }
248 }
249
250 // Iterate over all existing chunks.
251 // The allocator must be locked when calling this function.
252 void ForEachChunk(ForEachChunkCallback callback, void *arg) {
253 for (uptr region = 0; region < kNumPossibleRegions; region++)
254 if (possible_regions[region]) {
255 uptr chunk_size = ClassIdToSize(possible_regions[region]);
256 uptr max_chunks_in_region = kRegionSize / (chunk_size + kMetadataSize);
257 uptr region_beg = region * kRegionSize;
258 for (uptr chunk = region_beg;
259 chunk < region_beg + max_chunks_in_region * chunk_size;
260 chunk += chunk_size) {
261 // Too slow: CHECK_EQ((void *)chunk, GetBlockBegin((void *)chunk));
262 callback(chunk, arg);
263 }
264 }
265 }
266
267 void PrintStats() {}
268
269 static uptr AdditionalSize() { return 0; }
270
271 typedef SizeClassMap SizeClassMapT;
272 static const uptr kNumClasses = SizeClassMap::kNumClasses;
273
274 private:
275 static const uptr kRegionSize = 1 << kRegionSizeLog;
276 static const uptr kNumPossibleRegions = kSpaceSize / kRegionSize;
277
278 struct ALIGNED(SANITIZER_CACHE_LINE_SIZE) SizeClassInfo {
279 StaticSpinMutex mutex;
280 IntrusiveList<TransferBatch> free_list;
281 u32 rand_state;
282 };
283 COMPILER_CHECK(sizeof(SizeClassInfo) % kCacheLineSize == 0);
284
285 uptr ComputeRegionId(uptr mem) const {
286 if (SANITIZER_SIGN_EXTENDED_ADDRESSES)
287 mem &= (kSpaceSize - 1);
288 const uptr res = mem >> kRegionSizeLog;
289 CHECK_LT(res, kNumPossibleRegions);
290 return res;
291 }
292
293 uptr ComputeRegionBeg(uptr mem) {
294 return mem & ~(kRegionSize - 1);
295 }
296
297 uptr AllocateRegion(AllocatorStats *stat, uptr class_id) {
298 DCHECK_LT(class_id, kNumClasses);
299 const uptr res = reinterpret_cast<uptr>(MmapAlignedOrDieOnFatalError(
300 kRegionSize, kRegionSize, PrimaryAllocatorName));
301 if (UNLIKELY(!res))
302 return 0;
303 MapUnmapCallback().OnMap(res, kRegionSize);
304 stat->Add(AllocatorStatMapped, kRegionSize);
305 CHECK(IsAligned(res, kRegionSize));
306 possible_regions.set(ComputeRegionId(res), static_cast<u8>(class_id));
307 return res;
308 }
309
310 SizeClassInfo *GetSizeClassInfo(uptr class_id) {
311 DCHECK_LT(class_id, kNumClasses);
312 return &size_class_info_array[class_id];
313 }
314
315 bool PopulateBatches(AllocatorCache *c, SizeClassInfo *sci, uptr class_id,
316 TransferBatch **current_batch, uptr max_count,
317 uptr *pointers_array, uptr count) {
318 // If using a separate class for batches, we do not need to shuffle it.
319 if (kRandomShuffleChunks && (!kUseSeparateSizeClassForBatch ||
320 class_id != SizeClassMap::kBatchClassID))
321 RandomShuffle(pointers_array, count, &sci->rand_state);
322 TransferBatch *b = *current_batch;
323 for (uptr i = 0; i < count; i++) {
324 if (!b) {
325 b = c->CreateBatch(class_id, this, (TransferBatch*)pointers_array[i]);
326 if (UNLIKELY(!b))
327 return false;
328 b->Clear();
329 }
330 b->Add((void*)pointers_array[i]);
331 if (b->Count() == max_count) {
332 sci->free_list.push_back(b);
333 b = nullptr;
334 }
335 }
336 *current_batch = b;
337 return true;
338 }
339
340 bool PopulateFreeList(AllocatorStats *stat, AllocatorCache *c,
341 SizeClassInfo *sci, uptr class_id) {
342 const uptr region = AllocateRegion(stat, class_id);
343 if (UNLIKELY(!region))
344 return false;
345 if (kRandomShuffleChunks)
346 if (UNLIKELY(sci->rand_state == 0))
347 // The random state is initialized from ASLR (PIE) and time.
348 sci->rand_state = reinterpret_cast<uptr>(sci) ^ NanoTime();
349 const uptr size = ClassIdToSize(class_id);
350 const uptr n_chunks = kRegionSize / (size + kMetadataSize);
351 const uptr max_count = TransferBatch::MaxCached(size);
352 DCHECK_GT(max_count, 0);
353 TransferBatch *b = nullptr;
354 constexpr uptr kShuffleArraySize = 48;
355 uptr shuffle_array[kShuffleArraySize];
356 uptr count = 0;
357 for (uptr i = region; i < region + n_chunks * size; i += size) {
358 shuffle_array[count++] = i;
359 if (count == kShuffleArraySize) {
360 if (UNLIKELY(!PopulateBatches(c, sci, class_id, &b, max_count,
361 shuffle_array, count)))
362 return false;
363 count = 0;
364 }
365 }
366 if (count) {
367 if (UNLIKELY(!PopulateBatches(c, sci, class_id, &b, max_count,
368 shuffle_array, count)))
369 return false;
370 }
371 if (b) {
372 CHECK_GT(b->Count(), 0);
373 sci->free_list.push_back(b);
374 }
375 return true;
376 }
377
378 ByteMap possible_regions;
379 SizeClassInfo size_class_info_array[kNumClasses];
380};
lib/tsan/sanitizer_common/sanitizer_allocator_primary64.h created+863
...@@ -0,0 +1,863 @@
1//===-- sanitizer_allocator_primary64.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
16template<class SizeClassAllocator> struct SizeClassAllocator64LocalCache;
17
18// SizeClassAllocator64 -- allocator for 64-bit address space.
19// The template parameter Params is a class containing the actual parameters.
20//
21// Space: a portion of address space of kSpaceSize bytes starting at SpaceBeg.
22// If kSpaceBeg is ~0 then SpaceBeg is chosen dynamically my mmap.
23// Otherwise SpaceBeg=kSpaceBeg (fixed address).
24// kSpaceSize is a power of two.
25// At the beginning the entire space is mprotect-ed, then small parts of it
26// are mapped on demand.
27//
28// Region: a part of Space dedicated to a single size class.
29// There are kNumClasses Regions of equal size.
30//
31// UserChunk: a piece of memory returned to user.
32// MetaChunk: kMetadataSize bytes of metadata associated with a UserChunk.
33
34// FreeArray is an array free-d chunks (stored as 4-byte offsets)
35//
36// A Region looks like this:
37// UserChunk1 ... UserChunkN <gap> MetaChunkN ... MetaChunk1 FreeArray
38
39struct SizeClassAllocator64FlagMasks { // Bit masks.
40 enum {
41 kRandomShuffleChunks = 1,
42 };
43};
44
45template <class Params>
46class SizeClassAllocator64 {
47 public:
48 using AddressSpaceView = typename Params::AddressSpaceView;
49 static const uptr kSpaceBeg = Params::kSpaceBeg;
50 static const uptr kSpaceSize = Params::kSpaceSize;
51 static const uptr kMetadataSize = Params::kMetadataSize;
52 typedef typename Params::SizeClassMap SizeClassMap;
53 typedef typename Params::MapUnmapCallback MapUnmapCallback;
54
55 static const bool kRandomShuffleChunks =
56 Params::kFlags & SizeClassAllocator64FlagMasks::kRandomShuffleChunks;
57
58 typedef SizeClassAllocator64<Params> ThisT;
59 typedef SizeClassAllocator64LocalCache<ThisT> AllocatorCache;
60
61 // When we know the size class (the region base) we can represent a pointer
62 // as a 4-byte integer (offset from the region start shifted right by 4).
63 typedef u32 CompactPtrT;
64 static const uptr kCompactPtrScale = 4;
65 CompactPtrT PointerToCompactPtr(uptr base, uptr ptr) const {
66 return static_cast<CompactPtrT>((ptr - base) >> kCompactPtrScale);
67 }
68 uptr CompactPtrToPointer(uptr base, CompactPtrT ptr32) const {
69 return base + (static_cast<uptr>(ptr32) << kCompactPtrScale);
70 }
71
72 void Init(s32 release_to_os_interval_ms) {
73 uptr TotalSpaceSize = kSpaceSize + AdditionalSize();
74 if (kUsingConstantSpaceBeg) {
75 CHECK(IsAligned(kSpaceBeg, SizeClassMap::kMaxSize));
76 CHECK_EQ(kSpaceBeg, address_range.Init(TotalSpaceSize,
77 PrimaryAllocatorName, kSpaceBeg));
78 } else {
79 // Combined allocator expects that an 2^N allocation is always aligned to
80 // 2^N. For this to work, the start of the space needs to be aligned as
81 // high as the largest size class (which also needs to be a power of 2).
82 NonConstSpaceBeg = address_range.InitAligned(
83 TotalSpaceSize, SizeClassMap::kMaxSize, PrimaryAllocatorName);
84 CHECK_NE(NonConstSpaceBeg, ~(uptr)0);
85 }
86 SetReleaseToOSIntervalMs(release_to_os_interval_ms);
87 MapWithCallbackOrDie(SpaceEnd(), AdditionalSize(),
88 "SizeClassAllocator: region info");
89 // Check that the RegionInfo array is aligned on the CacheLine size.
90 DCHECK_EQ(SpaceEnd() % kCacheLineSize, 0);
91 }
92
93 s32 ReleaseToOSIntervalMs() const {
94 return atomic_load(&release_to_os_interval_ms_, memory_order_relaxed);
95 }
96
97 void SetReleaseToOSIntervalMs(s32 release_to_os_interval_ms) {
98 atomic_store(&release_to_os_interval_ms_, release_to_os_interval_ms,
99 memory_order_relaxed);
100 }
101
102 void ForceReleaseToOS() {
103 for (uptr class_id = 1; class_id < kNumClasses; class_id++) {
104 BlockingMutexLock l(&GetRegionInfo(class_id)->mutex);
105 MaybeReleaseToOS(class_id, true /*force*/);
106 }
107 }
108
109 static bool CanAllocate(uptr size, uptr alignment) {
110 return size <= SizeClassMap::kMaxSize &&
111 alignment <= SizeClassMap::kMaxSize;
112 }
113
114 NOINLINE void ReturnToAllocator(AllocatorStats *stat, uptr class_id,
115 const CompactPtrT *chunks, uptr n_chunks) {
116 RegionInfo *region = GetRegionInfo(class_id);
117 uptr region_beg = GetRegionBeginBySizeClass(class_id);
118 CompactPtrT *free_array = GetFreeArray(region_beg);
119
120 BlockingMutexLock l(&region->mutex);
121 uptr old_num_chunks = region->num_freed_chunks;
122 uptr new_num_freed_chunks = old_num_chunks + n_chunks;
123 // Failure to allocate free array space while releasing memory is non
124 // recoverable.
125 if (UNLIKELY(!EnsureFreeArraySpace(region, region_beg,
126 new_num_freed_chunks))) {
127 Report("FATAL: Internal error: %s's allocator exhausted the free list "
128 "space for size class %zd (%zd bytes).\n", SanitizerToolName,
129 class_id, ClassIdToSize(class_id));
130 Die();
131 }
132 for (uptr i = 0; i < n_chunks; i++)
133 free_array[old_num_chunks + i] = chunks[i];
134 region->num_freed_chunks = new_num_freed_chunks;
135 region->stats.n_freed += n_chunks;
136
137 MaybeReleaseToOS(class_id, false /*force*/);
138 }
139
140 NOINLINE bool GetFromAllocator(AllocatorStats *stat, uptr class_id,
141 CompactPtrT *chunks, uptr n_chunks) {
142 RegionInfo *region = GetRegionInfo(class_id);
143 uptr region_beg = GetRegionBeginBySizeClass(class_id);
144 CompactPtrT *free_array = GetFreeArray(region_beg);
145
146 BlockingMutexLock l(&region->mutex);
147 if (UNLIKELY(region->num_freed_chunks < n_chunks)) {
148 if (UNLIKELY(!PopulateFreeArray(stat, class_id, region,
149 n_chunks - region->num_freed_chunks)))
150 return false;
151 CHECK_GE(region->num_freed_chunks, n_chunks);
152 }
153 region->num_freed_chunks -= n_chunks;
154 uptr base_idx = region->num_freed_chunks;
155 for (uptr i = 0; i < n_chunks; i++)
156 chunks[i] = free_array[base_idx + i];
157 region->stats.n_allocated += n_chunks;
158 return true;
159 }
160
161 bool PointerIsMine(const void *p) const {
162 uptr P = reinterpret_cast<uptr>(p);
163 if (kUsingConstantSpaceBeg && (kSpaceBeg % kSpaceSize) == 0)
164 return P / kSpaceSize == kSpaceBeg / kSpaceSize;
165 return P >= SpaceBeg() && P < SpaceEnd();
166 }
167
168 uptr GetRegionBegin(const void *p) {
169 if (kUsingConstantSpaceBeg)
170 return reinterpret_cast<uptr>(p) & ~(kRegionSize - 1);
171 uptr space_beg = SpaceBeg();
172 return ((reinterpret_cast<uptr>(p) - space_beg) & ~(kRegionSize - 1)) +
173 space_beg;
174 }
175
176 uptr GetRegionBeginBySizeClass(uptr class_id) const {
177 return SpaceBeg() + kRegionSize * class_id;
178 }
179
180 uptr GetSizeClass(const void *p) {
181 if (kUsingConstantSpaceBeg && (kSpaceBeg % kSpaceSize) == 0)
182 return ((reinterpret_cast<uptr>(p)) / kRegionSize) % kNumClassesRounded;
183 return ((reinterpret_cast<uptr>(p) - SpaceBeg()) / kRegionSize) %
184 kNumClassesRounded;
185 }
186
187 void *GetBlockBegin(const void *p) {
188 uptr class_id = GetSizeClass(p);
189 uptr size = ClassIdToSize(class_id);
190 if (!size) return nullptr;
191 uptr chunk_idx = GetChunkIdx((uptr)p, size);
192 uptr reg_beg = GetRegionBegin(p);
193 uptr beg = chunk_idx * size;
194 uptr next_beg = beg + size;
195 if (class_id >= kNumClasses) return nullptr;
196 const RegionInfo *region = AddressSpaceView::Load(GetRegionInfo(class_id));
197 if (region->mapped_user >= next_beg)
198 return reinterpret_cast<void*>(reg_beg + beg);
199 return nullptr;
200 }
201
202 uptr GetActuallyAllocatedSize(void *p) {
203 CHECK(PointerIsMine(p));
204 return ClassIdToSize(GetSizeClass(p));
205 }
206
207 static uptr ClassID(uptr size) { return SizeClassMap::ClassID(size); }
208
209 void *GetMetaData(const void *p) {
210 uptr class_id = GetSizeClass(p);
211 uptr size = ClassIdToSize(class_id);
212 uptr chunk_idx = GetChunkIdx(reinterpret_cast<uptr>(p), size);
213 uptr region_beg = GetRegionBeginBySizeClass(class_id);
214 return reinterpret_cast<void *>(GetMetadataEnd(region_beg) -
215 (1 + chunk_idx) * kMetadataSize);
216 }
217
218 uptr TotalMemoryUsed() {
219 uptr res = 0;
220 for (uptr i = 0; i < kNumClasses; i++)
221 res += GetRegionInfo(i)->allocated_user;
222 return res;
223 }
224
225 // Test-only.
226 void TestOnlyUnmap() {
227 UnmapWithCallbackOrDie((uptr)address_range.base(), address_range.size());
228 }
229
230 static void FillMemoryProfile(uptr start, uptr rss, bool file, uptr *stats,
231 uptr stats_size) {
232 for (uptr class_id = 0; class_id < stats_size; class_id++)
233 if (stats[class_id] == start)
234 stats[class_id] = rss;
235 }
236
237 void PrintStats(uptr class_id, uptr rss) {
238 RegionInfo *region = GetRegionInfo(class_id);
239 if (region->mapped_user == 0) return;
240 uptr in_use = region->stats.n_allocated - region->stats.n_freed;
241 uptr avail_chunks = region->allocated_user / ClassIdToSize(class_id);
242 Printf(
243 "%s %02zd (%6zd): mapped: %6zdK allocs: %7zd frees: %7zd inuse: %6zd "
244 "num_freed_chunks %7zd avail: %6zd rss: %6zdK releases: %6zd "
245 "last released: %6zdK region: 0x%zx\n",
246 region->exhausted ? "F" : " ", class_id, ClassIdToSize(class_id),
247 region->mapped_user >> 10, region->stats.n_allocated,
248 region->stats.n_freed, in_use, region->num_freed_chunks, avail_chunks,
249 rss >> 10, region->rtoi.num_releases,
250 region->rtoi.last_released_bytes >> 10,
251 SpaceBeg() + kRegionSize * class_id);
252 }
253
254 void PrintStats() {
255 uptr rss_stats[kNumClasses];
256 for (uptr class_id = 0; class_id < kNumClasses; class_id++)
257 rss_stats[class_id] = SpaceBeg() + kRegionSize * class_id;
258 GetMemoryProfile(FillMemoryProfile, rss_stats, kNumClasses);
259
260 uptr total_mapped = 0;
261 uptr total_rss = 0;
262 uptr n_allocated = 0;
263 uptr n_freed = 0;
264 for (uptr class_id = 1; class_id < kNumClasses; class_id++) {
265 RegionInfo *region = GetRegionInfo(class_id);
266 if (region->mapped_user != 0) {
267 total_mapped += region->mapped_user;
268 total_rss += rss_stats[class_id];
269 }
270 n_allocated += region->stats.n_allocated;
271 n_freed += region->stats.n_freed;
272 }
273
274 Printf("Stats: SizeClassAllocator64: %zdM mapped (%zdM rss) in "
275 "%zd allocations; remains %zd\n", total_mapped >> 20,
276 total_rss >> 20, n_allocated, n_allocated - n_freed);
277 for (uptr class_id = 1; class_id < kNumClasses; class_id++)
278 PrintStats(class_id, rss_stats[class_id]);
279 }
280
281 // ForceLock() and ForceUnlock() are needed to implement Darwin malloc zone
282 // introspection API.
283 void ForceLock() {
284 for (uptr i = 0; i < kNumClasses; i++) {
285 GetRegionInfo(i)->mutex.Lock();
286 }
287 }
288
289 void ForceUnlock() {
290 for (int i = (int)kNumClasses - 1; i >= 0; i--) {
291 GetRegionInfo(i)->mutex.Unlock();
292 }
293 }
294
295 // Iterate over all existing chunks.
296 // The allocator must be locked when calling this function.
297 void ForEachChunk(ForEachChunkCallback callback, void *arg) {
298 for (uptr class_id = 1; class_id < kNumClasses; class_id++) {
299 RegionInfo *region = GetRegionInfo(class_id);
300 uptr chunk_size = ClassIdToSize(class_id);
301 uptr region_beg = SpaceBeg() + class_id * kRegionSize;
302 uptr region_allocated_user_size =
303 AddressSpaceView::Load(region)->allocated_user;
304 for (uptr chunk = region_beg;
305 chunk < region_beg + region_allocated_user_size;
306 chunk += chunk_size) {
307 // Too slow: CHECK_EQ((void *)chunk, GetBlockBegin((void *)chunk));
308 callback(chunk, arg);
309 }
310 }
311 }
312
313 static uptr ClassIdToSize(uptr class_id) {
314 return SizeClassMap::Size(class_id);
315 }
316
317 static uptr AdditionalSize() {
318 return RoundUpTo(sizeof(RegionInfo) * kNumClassesRounded,
319 GetPageSizeCached());
320 }
321
322 typedef SizeClassMap SizeClassMapT;
323 static const uptr kNumClasses = SizeClassMap::kNumClasses;
324 static const uptr kNumClassesRounded = SizeClassMap::kNumClassesRounded;
325
326 // A packed array of counters. Each counter occupies 2^n bits, enough to store
327 // counter's max_value. Ctor will try to allocate the required buffer via
328 // mapper->MapPackedCounterArrayBuffer and the caller is expected to check
329 // whether the initialization was successful by checking IsAllocated() result.
330 // For the performance sake, none of the accessors check the validity of the
331 // arguments, it is assumed that index is always in [0, n) range and the value
332 // is not incremented past max_value.
333 template<class MemoryMapperT>
334 class PackedCounterArray {
335 public:
336 PackedCounterArray(u64 num_counters, u64 max_value, MemoryMapperT *mapper)
337 : n(num_counters), memory_mapper(mapper) {
338 CHECK_GT(num_counters, 0);
339 CHECK_GT(max_value, 0);
340 constexpr u64 kMaxCounterBits = sizeof(*buffer) * 8ULL;
341 // Rounding counter storage size up to the power of two allows for using
342 // bit shifts calculating particular counter's index and offset.
343 uptr counter_size_bits =
344 RoundUpToPowerOfTwo(MostSignificantSetBitIndex(max_value) + 1);
345 CHECK_LE(counter_size_bits, kMaxCounterBits);
346 counter_size_bits_log = Log2(counter_size_bits);
347 counter_mask = ~0ULL >> (kMaxCounterBits - counter_size_bits);
348
349 uptr packing_ratio = kMaxCounterBits >> counter_size_bits_log;
350 CHECK_GT(packing_ratio, 0);
351 packing_ratio_log = Log2(packing_ratio);
352 bit_offset_mask = packing_ratio - 1;
353
354 buffer_size =
355 (RoundUpTo(n, 1ULL << packing_ratio_log) >> packing_ratio_log) *
356 sizeof(*buffer);
357 buffer = reinterpret_cast<u64*>(
358 memory_mapper->MapPackedCounterArrayBuffer(buffer_size));
359 }
360 ~PackedCounterArray() {
361 if (buffer) {
362 memory_mapper->UnmapPackedCounterArrayBuffer(
363 reinterpret_cast<uptr>(buffer), buffer_size);
364 }
365 }
366
367 bool IsAllocated() const {
368 return !!buffer;
369 }
370
371 u64 GetCount() const {
372 return n;
373 }
374
375 uptr Get(uptr i) const {
376 DCHECK_LT(i, n);
377 uptr index = i >> packing_ratio_log;
378 uptr bit_offset = (i & bit_offset_mask) << counter_size_bits_log;
379 return (buffer[index] >> bit_offset) & counter_mask;
380 }
381
382 void Inc(uptr i) const {
383 DCHECK_LT(Get(i), counter_mask);
384 uptr index = i >> packing_ratio_log;
385 uptr bit_offset = (i & bit_offset_mask) << counter_size_bits_log;
386 buffer[index] += 1ULL << bit_offset;
387 }
388
389 void IncRange(uptr from, uptr to) const {
390 DCHECK_LE(from, to);
391 for (uptr i = from; i <= to; i++)
392 Inc(i);
393 }
394
395 private:
396 const u64 n;
397 u64 counter_size_bits_log;
398 u64 counter_mask;
399 u64 packing_ratio_log;
400 u64 bit_offset_mask;
401
402 MemoryMapperT* const memory_mapper;
403 u64 buffer_size;
404 u64* buffer;
405 };
406
407 template<class MemoryMapperT>
408 class FreePagesRangeTracker {
409 public:
410 explicit FreePagesRangeTracker(MemoryMapperT* mapper)
411 : memory_mapper(mapper),
412 page_size_scaled_log(Log2(GetPageSizeCached() >> kCompactPtrScale)),
413 in_the_range(false), current_page(0), current_range_start_page(0) {}
414
415 void NextPage(bool freed) {
416 if (freed) {
417 if (!in_the_range) {
418 current_range_start_page = current_page;
419 in_the_range = true;
420 }
421 } else {
422 CloseOpenedRange();
423 }
424 current_page++;
425 }
426
427 void Done() {
428 CloseOpenedRange();
429 }
430
431 private:
432 void CloseOpenedRange() {
433 if (in_the_range) {
434 memory_mapper->ReleasePageRangeToOS(
435 current_range_start_page << page_size_scaled_log,
436 current_page << page_size_scaled_log);
437 in_the_range = false;
438 }
439 }
440
441 MemoryMapperT* const memory_mapper;
442 const uptr page_size_scaled_log;
443 bool in_the_range;
444 uptr current_page;
445 uptr current_range_start_page;
446 };
447
448 // Iterates over the free_array to identify memory pages containing freed
449 // chunks only and returns these pages back to OS.
450 // allocated_pages_count is the total number of pages allocated for the
451 // current bucket.
452 template<class MemoryMapperT>
453 static void ReleaseFreeMemoryToOS(CompactPtrT *free_array,
454 uptr free_array_count, uptr chunk_size,
455 uptr allocated_pages_count,
456 MemoryMapperT *memory_mapper) {
457 const uptr page_size = GetPageSizeCached();
458
459 // Figure out the number of chunks per page and whether we can take a fast
460 // path (the number of chunks per page is the same for all pages).
461 uptr full_pages_chunk_count_max;
462 bool same_chunk_count_per_page;
463 if (chunk_size <= page_size && page_size % chunk_size == 0) {
464 // Same number of chunks per page, no cross overs.
465 full_pages_chunk_count_max = page_size / chunk_size;
466 same_chunk_count_per_page = true;
467 } else if (chunk_size <= page_size && page_size % chunk_size != 0 &&
468 chunk_size % (page_size % chunk_size) == 0) {
469 // Some chunks are crossing page boundaries, which means that the page
470 // contains one or two partial chunks, but all pages contain the same
471 // number of chunks.
472 full_pages_chunk_count_max = page_size / chunk_size + 1;
473 same_chunk_count_per_page = true;
474 } else if (chunk_size <= page_size) {
475 // Some chunks are crossing page boundaries, which means that the page
476 // contains one or two partial chunks.
477 full_pages_chunk_count_max = page_size / chunk_size + 2;
478 same_chunk_count_per_page = false;
479 } else if (chunk_size > page_size && chunk_size % page_size == 0) {
480 // One chunk covers multiple pages, no cross overs.
481 full_pages_chunk_count_max = 1;
482 same_chunk_count_per_page = true;
483 } else if (chunk_size > page_size) {
484 // One chunk covers multiple pages, Some chunks are crossing page
485 // boundaries. Some pages contain one chunk, some contain two.
486 full_pages_chunk_count_max = 2;
487 same_chunk_count_per_page = false;
488 } else {
489 UNREACHABLE("All chunk_size/page_size ratios must be handled.");
490 }
491
492 PackedCounterArray<MemoryMapperT> counters(allocated_pages_count,
493 full_pages_chunk_count_max,
494 memory_mapper);
495 if (!counters.IsAllocated())
496 return;
497
498 const uptr chunk_size_scaled = chunk_size >> kCompactPtrScale;
499 const uptr page_size_scaled = page_size >> kCompactPtrScale;
500 const uptr page_size_scaled_log = Log2(page_size_scaled);
501
502 // Iterate over free chunks and count how many free chunks affect each
503 // allocated page.
504 if (chunk_size <= page_size && page_size % chunk_size == 0) {
505 // Each chunk affects one page only.
506 for (uptr i = 0; i < free_array_count; i++)
507 counters.Inc(free_array[i] >> page_size_scaled_log);
508 } else {
509 // In all other cases chunks might affect more than one page.
510 for (uptr i = 0; i < free_array_count; i++) {
511 counters.IncRange(
512 free_array[i] >> page_size_scaled_log,
513 (free_array[i] + chunk_size_scaled - 1) >> page_size_scaled_log);
514 }
515 }
516
517 // Iterate over pages detecting ranges of pages with chunk counters equal
518 // to the expected number of chunks for the particular page.
519 FreePagesRangeTracker<MemoryMapperT> range_tracker(memory_mapper);
520 if (same_chunk_count_per_page) {
521 // Fast path, every page has the same number of chunks affecting it.
522 for (uptr i = 0; i < counters.GetCount(); i++)
523 range_tracker.NextPage(counters.Get(i) == full_pages_chunk_count_max);
524 } else {
525 // Show path, go through the pages keeping count how many chunks affect
526 // each page.
527 const uptr pn =
528 chunk_size < page_size ? page_size_scaled / chunk_size_scaled : 1;
529 const uptr pnc = pn * chunk_size_scaled;
530 // The idea is to increment the current page pointer by the first chunk
531 // size, middle portion size (the portion of the page covered by chunks
532 // except the first and the last one) and then the last chunk size, adding
533 // up the number of chunks on the current page and checking on every step
534 // whether the page boundary was crossed.
535 uptr prev_page_boundary = 0;
536 uptr current_boundary = 0;
537 for (uptr i = 0; i < counters.GetCount(); i++) {
538 uptr page_boundary = prev_page_boundary + page_size_scaled;
539 uptr chunks_per_page = pn;
540 if (current_boundary < page_boundary) {
541 if (current_boundary > prev_page_boundary)
542 chunks_per_page++;
543 current_boundary += pnc;
544 if (current_boundary < page_boundary) {
545 chunks_per_page++;
546 current_boundary += chunk_size_scaled;
547 }
548 }
549 prev_page_boundary = page_boundary;
550
551 range_tracker.NextPage(counters.Get(i) == chunks_per_page);
552 }
553 }
554 range_tracker.Done();
555 }
556
557 private:
558 friend class MemoryMapper;
559
560 ReservedAddressRange address_range;
561
562 static const uptr kRegionSize = kSpaceSize / kNumClassesRounded;
563 // FreeArray is the array of free-d chunks (stored as 4-byte offsets).
564 // In the worst case it may reguire kRegionSize/SizeClassMap::kMinSize
565 // elements, but in reality this will not happen. For simplicity we
566 // dedicate 1/8 of the region's virtual space to FreeArray.
567 static const uptr kFreeArraySize = kRegionSize / 8;
568
569 static const bool kUsingConstantSpaceBeg = kSpaceBeg != ~(uptr)0;
570 uptr NonConstSpaceBeg;
571 uptr SpaceBeg() const {
572 return kUsingConstantSpaceBeg ? kSpaceBeg : NonConstSpaceBeg;
573 }
574 uptr SpaceEnd() const { return SpaceBeg() + kSpaceSize; }
575 // kRegionSize must be >= 2^32.
576 COMPILER_CHECK((kRegionSize) >= (1ULL << (SANITIZER_WORDSIZE / 2)));
577 // kRegionSize must be <= 2^36, see CompactPtrT.
578 COMPILER_CHECK((kRegionSize) <= (1ULL << (SANITIZER_WORDSIZE / 2 + 4)));
579 // Call mmap for user memory with at least this size.
580 static const uptr kUserMapSize = 1 << 16;
581 // Call mmap for metadata memory with at least this size.
582 static const uptr kMetaMapSize = 1 << 16;
583 // Call mmap for free array memory with at least this size.
584 static const uptr kFreeArrayMapSize = 1 << 16;
585
586 atomic_sint32_t release_to_os_interval_ms_;
587
588 struct Stats {
589 uptr n_allocated;
590 uptr n_freed;
591 };
592
593 struct ReleaseToOsInfo {
594 uptr n_freed_at_last_release;
595 uptr num_releases;
596 u64 last_release_at_ns;
597 u64 last_released_bytes;
598 };
599
600 struct ALIGNED(SANITIZER_CACHE_LINE_SIZE) RegionInfo {
601 BlockingMutex mutex;
602 uptr num_freed_chunks; // Number of elements in the freearray.
603 uptr mapped_free_array; // Bytes mapped for freearray.
604 uptr allocated_user; // Bytes allocated for user memory.
605 uptr allocated_meta; // Bytes allocated for metadata.
606 uptr mapped_user; // Bytes mapped for user memory.
607 uptr mapped_meta; // Bytes mapped for metadata.
608 u32 rand_state; // Seed for random shuffle, used if kRandomShuffleChunks.
609 bool exhausted; // Whether region is out of space for new chunks.
610 Stats stats;
611 ReleaseToOsInfo rtoi;
612 };
613 COMPILER_CHECK(sizeof(RegionInfo) % kCacheLineSize == 0);
614
615 RegionInfo *GetRegionInfo(uptr class_id) const {
616 DCHECK_LT(class_id, kNumClasses);
617 RegionInfo *regions = reinterpret_cast<RegionInfo *>(SpaceEnd());
618 return &regions[class_id];
619 }
620
621 uptr GetMetadataEnd(uptr region_beg) const {
622 return region_beg + kRegionSize - kFreeArraySize;
623 }
624
625 uptr GetChunkIdx(uptr chunk, uptr size) const {
626 if (!kUsingConstantSpaceBeg)
627 chunk -= SpaceBeg();
628
629 uptr offset = chunk % kRegionSize;
630 // Here we divide by a non-constant. This is costly.
631 // size always fits into 32-bits. If the offset fits too, use 32-bit div.
632 if (offset >> (SANITIZER_WORDSIZE / 2))
633 return offset / size;
634 return (u32)offset / (u32)size;
635 }
636
637 CompactPtrT *GetFreeArray(uptr region_beg) const {
638 return reinterpret_cast<CompactPtrT *>(GetMetadataEnd(region_beg));
639 }
640
641 bool MapWithCallback(uptr beg, uptr size, const char *name) {
642 uptr mapped = address_range.Map(beg, size, name);
643 if (UNLIKELY(!mapped))
644 return false;
645 CHECK_EQ(beg, mapped);
646 MapUnmapCallback().OnMap(beg, size);
647 return true;
648 }
649
650 void MapWithCallbackOrDie(uptr beg, uptr size, const char *name) {
651 CHECK_EQ(beg, address_range.MapOrDie(beg, size, name));
652 MapUnmapCallback().OnMap(beg, size);
653 }
654
655 void UnmapWithCallbackOrDie(uptr beg, uptr size) {
656 MapUnmapCallback().OnUnmap(beg, size);
657 address_range.Unmap(beg, size);
658 }
659
660 bool EnsureFreeArraySpace(RegionInfo *region, uptr region_beg,
661 uptr num_freed_chunks) {
662 uptr needed_space = num_freed_chunks * sizeof(CompactPtrT);
663 if (region->mapped_free_array < needed_space) {
664 uptr new_mapped_free_array = RoundUpTo(needed_space, kFreeArrayMapSize);
665 CHECK_LE(new_mapped_free_array, kFreeArraySize);
666 uptr current_map_end = reinterpret_cast<uptr>(GetFreeArray(region_beg)) +
667 region->mapped_free_array;
668 uptr new_map_size = new_mapped_free_array - region->mapped_free_array;
669 if (UNLIKELY(!MapWithCallback(current_map_end, new_map_size,
670 "SizeClassAllocator: freearray")))
671 return false;
672 region->mapped_free_array = new_mapped_free_array;
673 }
674 return true;
675 }
676
677 // Check whether this size class is exhausted.
678 bool IsRegionExhausted(RegionInfo *region, uptr class_id,
679 uptr additional_map_size) {
680 if (LIKELY(region->mapped_user + region->mapped_meta +
681 additional_map_size <= kRegionSize - kFreeArraySize))
682 return false;
683 if (!region->exhausted) {
684 region->exhausted = true;
685 Printf("%s: Out of memory. ", SanitizerToolName);
686 Printf("The process has exhausted %zuMB for size class %zu.\n",
687 kRegionSize >> 20, ClassIdToSize(class_id));
688 }
689 return true;
690 }
691
692 NOINLINE bool PopulateFreeArray(AllocatorStats *stat, uptr class_id,
693 RegionInfo *region, uptr requested_count) {
694 // region->mutex is held.
695 const uptr region_beg = GetRegionBeginBySizeClass(class_id);
696 const uptr size = ClassIdToSize(class_id);
697
698 const uptr total_user_bytes =
699 region->allocated_user + requested_count * size;
700 // Map more space for chunks, if necessary.
701 if (LIKELY(total_user_bytes > region->mapped_user)) {
702 if (UNLIKELY(region->mapped_user == 0)) {
703 if (!kUsingConstantSpaceBeg && kRandomShuffleChunks)
704 // The random state is initialized from ASLR.
705 region->rand_state = static_cast<u32>(region_beg >> 12);
706 // Postpone the first release to OS attempt for ReleaseToOSIntervalMs,
707 // preventing just allocated memory from being released sooner than
708 // necessary and also preventing extraneous ReleaseMemoryPagesToOS calls
709 // for short lived processes.
710 // Do it only when the feature is turned on, to avoid a potentially
711 // extraneous syscall.
712 if (ReleaseToOSIntervalMs() >= 0)
713 region->rtoi.last_release_at_ns = MonotonicNanoTime();
714 }
715 // Do the mmap for the user memory.
716 const uptr user_map_size =
717 RoundUpTo(total_user_bytes - region->mapped_user, kUserMapSize);
718 if (UNLIKELY(IsRegionExhausted(region, class_id, user_map_size)))
719 return false;
720 if (UNLIKELY(!MapWithCallback(region_beg + region->mapped_user,
721 user_map_size,
722 "SizeClassAllocator: region data")))
723 return false;
724 stat->Add(AllocatorStatMapped, user_map_size);
725 region->mapped_user += user_map_size;
726 }
727 const uptr new_chunks_count =
728 (region->mapped_user - region->allocated_user) / size;
729
730 if (kMetadataSize) {
731 // Calculate the required space for metadata.
732 const uptr total_meta_bytes =
733 region->allocated_meta + new_chunks_count * kMetadataSize;
734 const uptr meta_map_size = (total_meta_bytes > region->mapped_meta) ?
735 RoundUpTo(total_meta_bytes - region->mapped_meta, kMetaMapSize) : 0;
736 // Map more space for metadata, if necessary.
737 if (meta_map_size) {
738 if (UNLIKELY(IsRegionExhausted(region, class_id, meta_map_size)))
739 return false;
740 if (UNLIKELY(!MapWithCallback(
741 GetMetadataEnd(region_beg) - region->mapped_meta - meta_map_size,
742 meta_map_size, "SizeClassAllocator: region metadata")))
743 return false;
744 region->mapped_meta += meta_map_size;
745 }
746 }
747
748 // If necessary, allocate more space for the free array and populate it with
749 // newly allocated chunks.
750 const uptr total_freed_chunks = region->num_freed_chunks + new_chunks_count;
751 if (UNLIKELY(!EnsureFreeArraySpace(region, region_beg, total_freed_chunks)))
752 return false;
753 CompactPtrT *free_array = GetFreeArray(region_beg);
754 for (uptr i = 0, chunk = region->allocated_user; i < new_chunks_count;
755 i++, chunk += size)
756 free_array[total_freed_chunks - 1 - i] = PointerToCompactPtr(0, chunk);
757 if (kRandomShuffleChunks)
758 RandomShuffle(&free_array[region->num_freed_chunks], new_chunks_count,
759 &region->rand_state);
760
761 // All necessary memory is mapped and now it is safe to advance all
762 // 'allocated_*' counters.
763 region->num_freed_chunks += new_chunks_count;
764 region->allocated_user += new_chunks_count * size;
765 CHECK_LE(region->allocated_user, region->mapped_user);
766 region->allocated_meta += new_chunks_count * kMetadataSize;
767 CHECK_LE(region->allocated_meta, region->mapped_meta);
768 region->exhausted = false;
769
770 // TODO(alekseyshl): Consider bumping last_release_at_ns here to prevent
771 // MaybeReleaseToOS from releasing just allocated pages or protect these
772 // not yet used chunks some other way.
773
774 return true;
775 }
776
777 class MemoryMapper {
778 public:
779 MemoryMapper(const ThisT& base_allocator, uptr class_id)
780 : allocator(base_allocator),
781 region_base(base_allocator.GetRegionBeginBySizeClass(class_id)),
782 released_ranges_count(0),
783 released_bytes(0) {
784 }
785
786 uptr GetReleasedRangesCount() const {
787 return released_ranges_count;
788 }
789
790 uptr GetReleasedBytes() const {
791 return released_bytes;
792 }
793
794 uptr MapPackedCounterArrayBuffer(uptr buffer_size) {
795 // TODO(alekseyshl): The idea to explore is to check if we have enough
796 // space between num_freed_chunks*sizeof(CompactPtrT) and
797 // mapped_free_array to fit buffer_size bytes and use that space instead
798 // of mapping a temporary one.
799 return reinterpret_cast<uptr>(
800 MmapOrDieOnFatalError(buffer_size, "ReleaseToOSPageCounters"));
801 }
802
803 void UnmapPackedCounterArrayBuffer(uptr buffer, uptr buffer_size) {
804 UnmapOrDie(reinterpret_cast<void *>(buffer), buffer_size);
805 }
806
807 // Releases [from, to) range of pages back to OS.
808 void ReleasePageRangeToOS(CompactPtrT from, CompactPtrT to) {
809 const uptr from_page = allocator.CompactPtrToPointer(region_base, from);
810 const uptr to_page = allocator.CompactPtrToPointer(region_base, to);
811 ReleaseMemoryPagesToOS(from_page, to_page);
812 released_ranges_count++;
813 released_bytes += to_page - from_page;
814 }
815
816 private:
817 const ThisT& allocator;
818 const uptr region_base;
819 uptr released_ranges_count;
820 uptr released_bytes;
821 };
822
823 // Attempts to release RAM occupied by freed chunks back to OS. The region is
824 // expected to be locked.
825 void MaybeReleaseToOS(uptr class_id, bool force) {
826 RegionInfo *region = GetRegionInfo(class_id);
827 const uptr chunk_size = ClassIdToSize(class_id);
828 const uptr page_size = GetPageSizeCached();
829
830 uptr n = region->num_freed_chunks;
831 if (n * chunk_size < page_size)
832 return; // No chance to release anything.
833 if ((region->stats.n_freed -
834 region->rtoi.n_freed_at_last_release) * chunk_size < page_size) {
835 return; // Nothing new to release.
836 }
837
838 if (!force) {
839 s32 interval_ms = ReleaseToOSIntervalMs();
840 if (interval_ms < 0)
841 return;
842
843 if (region->rtoi.last_release_at_ns + interval_ms * 1000000ULL >
844 MonotonicNanoTime()) {
845 return; // Memory was returned recently.
846 }
847 }
848
849 MemoryMapper memory_mapper(*this, class_id);
850
851 ReleaseFreeMemoryToOS<MemoryMapper>(
852 GetFreeArray(GetRegionBeginBySizeClass(class_id)), n, chunk_size,
853 RoundUpTo(region->allocated_user, page_size) / page_size,
854 &memory_mapper);
855
856 if (memory_mapper.GetReleasedRangesCount() > 0) {
857 region->rtoi.n_freed_at_last_release = region->stats.n_freed;
858 region->rtoi.num_releases += memory_mapper.GetReleasedRangesCount();
859 region->rtoi.last_released_bytes = memory_mapper.GetReleasedBytes();
860 }
861 region->rtoi.last_release_at_ns = MonotonicNanoTime();
862 }
863};
lib/tsan/sanitizer_common/sanitizer_allocator_report.h created+39
...@@ -0,0 +1,39 @@
1//===-- sanitizer_allocator_report.h ----------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// Shared allocator error reporting for ThreadSanitizer, MemorySanitizer, etc.
11///
12//===----------------------------------------------------------------------===//
13
14#ifndef SANITIZER_ALLOCATOR_REPORT_H
15#define SANITIZER_ALLOCATOR_REPORT_H
16
17#include "sanitizer_internal_defs.h"
18#include "sanitizer_stacktrace.h"
19
20namespace __sanitizer {
21
22void NORETURN ReportCallocOverflow(uptr count, uptr size,
23 const StackTrace *stack);
24void NORETURN ReportReallocArrayOverflow(uptr count, uptr size,
25 const StackTrace *stack);
26void NORETURN ReportPvallocOverflow(uptr size, const StackTrace *stack);
27void NORETURN ReportInvalidAllocationAlignment(uptr alignment,
28 const StackTrace *stack);
29void NORETURN ReportInvalidAlignedAllocAlignment(uptr size, uptr alignment,
30 const StackTrace *stack);
31void NORETURN ReportInvalidPosixMemalignAlignment(uptr alignment,
32 const StackTrace *stack);
33void NORETURN ReportAllocationSizeTooBig(uptr user_size, uptr max_size,
34 const StackTrace *stack);
35void NORETURN ReportOutOfMemory(uptr requested_size, const StackTrace *stack);
36
37} // namespace __sanitizer
38
39#endif // SANITIZER_ALLOCATOR_REPORT_H
lib/tsan/sanitizer_common/sanitizer_allocator_secondary.h created+326
...@@ -0,0 +1,326 @@
1//===-- sanitizer_allocator_secondary.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// Fixed array to store LargeMmapAllocator chunks list, limited to 32K total
17// allocated chunks. To be used in memory constrained or not memory hungry cases
18// (currently, 32 bits and internal allocator).
19class LargeMmapAllocatorPtrArrayStatic {
20 public:
21 INLINE void *Init() { return &p_[0]; }
22 INLINE void EnsureSpace(uptr n) { CHECK_LT(n, kMaxNumChunks); }
23 private:
24 static const int kMaxNumChunks = 1 << 15;
25 uptr p_[kMaxNumChunks];
26};
27
28// Much less restricted LargeMmapAllocator chunks list (comparing to
29// PtrArrayStatic). Backed by mmaped memory region and can hold up to 1M chunks.
30// ReservedAddressRange was used instead of just MAP_NORESERVE to achieve the
31// same functionality in Fuchsia case, which does not support MAP_NORESERVE.
32class LargeMmapAllocatorPtrArrayDynamic {
33 public:
34 INLINE void *Init() {
35 uptr p = address_range_.Init(kMaxNumChunks * sizeof(uptr),
36 SecondaryAllocatorName);
37 CHECK(p);
38 return reinterpret_cast<void*>(p);
39 }
40
41 INLINE void EnsureSpace(uptr n) {
42 CHECK_LT(n, kMaxNumChunks);
43 DCHECK(n <= n_reserved_);
44 if (UNLIKELY(n == n_reserved_)) {
45 address_range_.MapOrDie(
46 reinterpret_cast<uptr>(address_range_.base()) +
47 n_reserved_ * sizeof(uptr),
48 kChunksBlockCount * sizeof(uptr));
49 n_reserved_ += kChunksBlockCount;
50 }
51 }
52
53 private:
54 static const int kMaxNumChunks = 1 << 20;
55 static const int kChunksBlockCount = 1 << 14;
56 ReservedAddressRange address_range_;
57 uptr n_reserved_;
58};
59
60#if SANITIZER_WORDSIZE == 32
61typedef LargeMmapAllocatorPtrArrayStatic DefaultLargeMmapAllocatorPtrArray;
62#else
63typedef LargeMmapAllocatorPtrArrayDynamic DefaultLargeMmapAllocatorPtrArray;
64#endif
65
66// This class can (de)allocate only large chunks of memory using mmap/unmap.
67// The main purpose of this allocator is to cover large and rare allocation
68// sizes not covered by more efficient allocators (e.g. SizeClassAllocator64).
69template <class MapUnmapCallback = NoOpMapUnmapCallback,
70 class PtrArrayT = DefaultLargeMmapAllocatorPtrArray,
71 class AddressSpaceViewTy = LocalAddressSpaceView>
72class LargeMmapAllocator {
73 public:
74 using AddressSpaceView = AddressSpaceViewTy;
75 void InitLinkerInitialized() {
76 page_size_ = GetPageSizeCached();
77 chunks_ = reinterpret_cast<Header**>(ptr_array_.Init());
78 }
79
80 void Init() {
81 internal_memset(this, 0, sizeof(*this));
82 InitLinkerInitialized();
83 }
84
85 void *Allocate(AllocatorStats *stat, uptr size, uptr alignment) {
86 CHECK(IsPowerOfTwo(alignment));
87 uptr map_size = RoundUpMapSize(size);
88 if (alignment > page_size_)
89 map_size += alignment;
90 // Overflow.
91 if (map_size < size) {
92 Report("WARNING: %s: LargeMmapAllocator allocation overflow: "
93 "0x%zx bytes with 0x%zx alignment requested\n",
94 SanitizerToolName, map_size, alignment);
95 return nullptr;
96 }
97 uptr map_beg = reinterpret_cast<uptr>(
98 MmapOrDieOnFatalError(map_size, SecondaryAllocatorName));
99 if (!map_beg)
100 return nullptr;
101 CHECK(IsAligned(map_beg, page_size_));
102 MapUnmapCallback().OnMap(map_beg, map_size);
103 uptr map_end = map_beg + map_size;
104 uptr res = map_beg + page_size_;
105 if (res & (alignment - 1)) // Align.
106 res += alignment - (res & (alignment - 1));
107 CHECK(IsAligned(res, alignment));
108 CHECK(IsAligned(res, page_size_));
109 CHECK_GE(res + size, map_beg);
110 CHECK_LE(res + size, map_end);
111 Header *h = GetHeader(res);
112 h->size = size;
113 h->map_beg = map_beg;
114 h->map_size = map_size;
115 uptr size_log = MostSignificantSetBitIndex(map_size);
116 CHECK_LT(size_log, ARRAY_SIZE(stats.by_size_log));
117 {
118 SpinMutexLock l(&mutex_);
119 ptr_array_.EnsureSpace(n_chunks_);
120 uptr idx = n_chunks_++;
121 h->chunk_idx = idx;
122 chunks_[idx] = h;
123 chunks_sorted_ = false;
124 stats.n_allocs++;
125 stats.currently_allocated += map_size;
126 stats.max_allocated = Max(stats.max_allocated, stats.currently_allocated);
127 stats.by_size_log[size_log]++;
128 stat->Add(AllocatorStatAllocated, map_size);
129 stat->Add(AllocatorStatMapped, map_size);
130 }
131 return reinterpret_cast<void*>(res);
132 }
133
134 void Deallocate(AllocatorStats *stat, void *p) {
135 Header *h = GetHeader(p);
136 {
137 SpinMutexLock l(&mutex_);
138 uptr idx = h->chunk_idx;
139 CHECK_EQ(chunks_[idx], h);
140 CHECK_LT(idx, n_chunks_);
141 chunks_[idx] = chunks_[--n_chunks_];
142 chunks_[idx]->chunk_idx = idx;
143 chunks_sorted_ = false;
144 stats.n_frees++;
145 stats.currently_allocated -= h->map_size;
146 stat->Sub(AllocatorStatAllocated, h->map_size);
147 stat->Sub(AllocatorStatMapped, h->map_size);
148 }
149 MapUnmapCallback().OnUnmap(h->map_beg, h->map_size);
150 UnmapOrDie(reinterpret_cast<void*>(h->map_beg), h->map_size);
151 }
152
153 uptr TotalMemoryUsed() {
154 SpinMutexLock l(&mutex_);
155 uptr res = 0;
156 for (uptr i = 0; i < n_chunks_; i++) {
157 Header *h = chunks_[i];
158 CHECK_EQ(h->chunk_idx, i);
159 res += RoundUpMapSize(h->size);
160 }
161 return res;
162 }
163
164 bool PointerIsMine(const void *p) {
165 return GetBlockBegin(p) != nullptr;
166 }
167
168 uptr GetActuallyAllocatedSize(void *p) {
169 return RoundUpTo(GetHeader(p)->size, page_size_);
170 }
171
172 // At least page_size_/2 metadata bytes is available.
173 void *GetMetaData(const void *p) {
174 // Too slow: CHECK_EQ(p, GetBlockBegin(p));
175 if (!IsAligned(reinterpret_cast<uptr>(p), page_size_)) {
176 Printf("%s: bad pointer %p\n", SanitizerToolName, p);
177 CHECK(IsAligned(reinterpret_cast<uptr>(p), page_size_));
178 }
179 return GetHeader(p) + 1;
180 }
181
182 void *GetBlockBegin(const void *ptr) {
183 uptr p = reinterpret_cast<uptr>(ptr);
184 SpinMutexLock l(&mutex_);
185 uptr nearest_chunk = 0;
186 Header *const *chunks = AddressSpaceView::Load(chunks_, n_chunks_);
187 // Cache-friendly linear search.
188 for (uptr i = 0; i < n_chunks_; i++) {
189 uptr ch = reinterpret_cast<uptr>(chunks[i]);
190 if (p < ch) continue; // p is at left to this chunk, skip it.
191 if (p - ch < p - nearest_chunk)
192 nearest_chunk = ch;
193 }
194 if (!nearest_chunk)
195 return nullptr;
196 const Header *h =
197 AddressSpaceView::Load(reinterpret_cast<Header *>(nearest_chunk));
198 Header *h_ptr = reinterpret_cast<Header *>(nearest_chunk);
199 CHECK_GE(nearest_chunk, h->map_beg);
200 CHECK_LT(nearest_chunk, h->map_beg + h->map_size);
201 CHECK_LE(nearest_chunk, p);
202 if (h->map_beg + h->map_size <= p)
203 return nullptr;
204 return GetUser(h_ptr);
205 }
206
207 void EnsureSortedChunks() {
208 if (chunks_sorted_) return;
209 Header **chunks = AddressSpaceView::LoadWritable(chunks_, n_chunks_);
210 Sort(reinterpret_cast<uptr *>(chunks), n_chunks_);
211 for (uptr i = 0; i < n_chunks_; i++)
212 AddressSpaceView::LoadWritable(chunks[i])->chunk_idx = i;
213 chunks_sorted_ = true;
214 }
215
216 // This function does the same as GetBlockBegin, but is much faster.
217 // Must be called with the allocator locked.
218 void *GetBlockBeginFastLocked(void *ptr) {
219 mutex_.CheckLocked();
220 uptr p = reinterpret_cast<uptr>(ptr);
221 uptr n = n_chunks_;
222 if (!n) return nullptr;
223 EnsureSortedChunks();
224 Header *const *chunks = AddressSpaceView::Load(chunks_, n_chunks_);
225 auto min_mmap_ = reinterpret_cast<uptr>(chunks[0]);
226 auto max_mmap_ = reinterpret_cast<uptr>(chunks[n - 1]) +
227 AddressSpaceView::Load(chunks[n - 1])->map_size;
228 if (p < min_mmap_ || p >= max_mmap_)
229 return nullptr;
230 uptr beg = 0, end = n - 1;
231 // This loop is a log(n) lower_bound. It does not check for the exact match
232 // to avoid expensive cache-thrashing loads.
233 while (end - beg >= 2) {
234 uptr mid = (beg + end) / 2; // Invariant: mid >= beg + 1
235 if (p < reinterpret_cast<uptr>(chunks[mid]))
236 end = mid - 1; // We are not interested in chunks[mid].
237 else
238 beg = mid; // chunks[mid] may still be what we want.
239 }
240
241 if (beg < end) {
242 CHECK_EQ(beg + 1, end);
243 // There are 2 chunks left, choose one.
244 if (p >= reinterpret_cast<uptr>(chunks[end]))
245 beg = end;
246 }
247
248 const Header *h = AddressSpaceView::Load(chunks[beg]);
249 Header *h_ptr = chunks[beg];
250 if (h->map_beg + h->map_size <= p || p < h->map_beg)
251 return nullptr;
252 return GetUser(h_ptr);
253 }
254
255 void PrintStats() {
256 Printf("Stats: LargeMmapAllocator: allocated %zd times, "
257 "remains %zd (%zd K) max %zd M; by size logs: ",
258 stats.n_allocs, stats.n_allocs - stats.n_frees,
259 stats.currently_allocated >> 10, stats.max_allocated >> 20);
260 for (uptr i = 0; i < ARRAY_SIZE(stats.by_size_log); i++) {
261 uptr c = stats.by_size_log[i];
262 if (!c) continue;
263 Printf("%zd:%zd; ", i, c);
264 }
265 Printf("\n");
266 }
267
268 // ForceLock() and ForceUnlock() are needed to implement Darwin malloc zone
269 // introspection API.
270 void ForceLock() {
271 mutex_.Lock();
272 }
273
274 void ForceUnlock() {
275 mutex_.Unlock();
276 }
277
278 // Iterate over all existing chunks.
279 // The allocator must be locked when calling this function.
280 void ForEachChunk(ForEachChunkCallback callback, void *arg) {
281 EnsureSortedChunks(); // Avoid doing the sort while iterating.
282 const Header *const *chunks = AddressSpaceView::Load(chunks_, n_chunks_);
283 for (uptr i = 0; i < n_chunks_; i++) {
284 const Header *t = chunks[i];
285 callback(reinterpret_cast<uptr>(GetUser(t)), arg);
286 // Consistency check: verify that the array did not change.
287 CHECK_EQ(chunks[i], t);
288 CHECK_EQ(AddressSpaceView::Load(chunks[i])->chunk_idx, i);
289 }
290 }
291
292 private:
293 struct Header {
294 uptr map_beg;
295 uptr map_size;
296 uptr size;
297 uptr chunk_idx;
298 };
299
300 Header *GetHeader(uptr p) {
301 CHECK(IsAligned(p, page_size_));
302 return reinterpret_cast<Header*>(p - page_size_);
303 }
304 Header *GetHeader(const void *p) {
305 return GetHeader(reinterpret_cast<uptr>(p));
306 }
307
308 void *GetUser(const Header *h) {
309 CHECK(IsAligned((uptr)h, page_size_));
310 return reinterpret_cast<void*>(reinterpret_cast<uptr>(h) + page_size_);
311 }
312
313 uptr RoundUpMapSize(uptr size) {
314 return RoundUpTo(size, page_size_) + page_size_;
315 }
316
317 uptr page_size_;
318 Header **chunks_;
319 PtrArrayT ptr_array_;
320 uptr n_chunks_;
321 bool chunks_sorted_;
322 struct Stats {
323 uptr n_allocs, n_frees, currently_allocated, max_allocated, by_size_log[64];
324 } stats;
325 StaticSpinMutex mutex_;
326};
lib/tsan/sanitizer_common/sanitizer_allocator_size_class_map.h created+241
...@@ -0,0 +1,241 @@
1//===-- sanitizer_allocator_size_class_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#ifndef SANITIZER_ALLOCATOR_H
13#error This file must be included inside sanitizer_allocator.h
14#endif
15
16// SizeClassMap maps allocation sizes into size classes and back.
17// Class 0 always corresponds to size 0.
18// The other sizes are controlled by the template parameters:
19// kMinSizeLog: defines the class 1 as 2^kMinSizeLog.
20// kMaxSizeLog: defines the last class as 2^kMaxSizeLog.
21// kMidSizeLog: the classes starting from 1 increase with step
22// 2^kMinSizeLog until 2^kMidSizeLog.
23// kNumBits: the number of non-zero bits in sizes after 2^kMidSizeLog.
24// E.g. with kNumBits==3 all size classes after 2^kMidSizeLog
25// look like 0b1xx0..0, where x is either 0 or 1.
26//
27// Example: kNumBits=3, kMidSizeLog=4, kMidSizeLog=8, kMaxSizeLog=17:
28//
29// Classes 1 - 16 correspond to sizes 16 to 256 (size = class_id * 16).
30// Next 4 classes: 256 + i * 64 (i = 1 to 4).
31// Next 4 classes: 512 + i * 128 (i = 1 to 4).
32// ...
33// Next 4 classes: 2^k + i * 2^(k-2) (i = 1 to 4).
34// Last class corresponds to kMaxSize = 1 << kMaxSizeLog.
35//
36// This structure of the size class map gives us:
37// - Efficient table-free class-to-size and size-to-class functions.
38// - Difference between two consequent size classes is between 14% and 25%
39//
40// This class also gives a hint to a thread-caching allocator about the amount
41// of chunks that need to be cached per-thread:
42// - kMaxNumCachedHint is a hint for maximal number of chunks per size class.
43// The actual number is computed in TransferBatch.
44// - (1 << kMaxBytesCachedLog) is the maximal number of bytes per size class.
45//
46// Part of output of SizeClassMap::Print():
47// c00 => s: 0 diff: +0 00% l 0 cached: 0 0; id 0
48// c01 => s: 16 diff: +16 00% l 4 cached: 256 4096; id 1
49// c02 => s: 32 diff: +16 100% l 5 cached: 256 8192; id 2
50// c03 => s: 48 diff: +16 50% l 5 cached: 256 12288; id 3
51// c04 => s: 64 diff: +16 33% l 6 cached: 256 16384; id 4
52// c05 => s: 80 diff: +16 25% l 6 cached: 256 20480; id 5
53// c06 => s: 96 diff: +16 20% l 6 cached: 256 24576; id 6
54// c07 => s: 112 diff: +16 16% l 6 cached: 256 28672; id 7
55//
56// c08 => s: 128 diff: +16 14% l 7 cached: 256 32768; id 8
57// c09 => s: 144 diff: +16 12% l 7 cached: 256 36864; id 9
58// c10 => s: 160 diff: +16 11% l 7 cached: 256 40960; id 10
59// c11 => s: 176 diff: +16 10% l 7 cached: 256 45056; id 11
60// c12 => s: 192 diff: +16 09% l 7 cached: 256 49152; id 12
61// c13 => s: 208 diff: +16 08% l 7 cached: 256 53248; id 13
62// c14 => s: 224 diff: +16 07% l 7 cached: 256 57344; id 14
63// c15 => s: 240 diff: +16 07% l 7 cached: 256 61440; id 15
64//
65// c16 => s: 256 diff: +16 06% l 8 cached: 256 65536; id 16
66// c17 => s: 320 diff: +64 25% l 8 cached: 204 65280; id 17
67// c18 => s: 384 diff: +64 20% l 8 cached: 170 65280; id 18
68// c19 => s: 448 diff: +64 16% l 8 cached: 146 65408; id 19
69//
70// c20 => s: 512 diff: +64 14% l 9 cached: 128 65536; id 20
71// c21 => s: 640 diff: +128 25% l 9 cached: 102 65280; id 21
72// c22 => s: 768 diff: +128 20% l 9 cached: 85 65280; id 22
73// c23 => s: 896 diff: +128 16% l 9 cached: 73 65408; id 23
74//
75// c24 => s: 1024 diff: +128 14% l 10 cached: 64 65536; id 24
76// c25 => s: 1280 diff: +256 25% l 10 cached: 51 65280; id 25
77// c26 => s: 1536 diff: +256 20% l 10 cached: 42 64512; id 26
78// c27 => s: 1792 diff: +256 16% l 10 cached: 36 64512; id 27
79//
80// ...
81//
82// c48 => s: 65536 diff: +8192 14% l 16 cached: 1 65536; id 48
83// c49 => s: 81920 diff: +16384 25% l 16 cached: 1 81920; id 49
84// c50 => s: 98304 diff: +16384 20% l 16 cached: 1 98304; id 50
85// c51 => s: 114688 diff: +16384 16% l 16 cached: 1 114688; id 51
86//
87// c52 => s: 131072 diff: +16384 14% l 17 cached: 1 131072; id 52
88//
89//
90// Another example (kNumBits=2):
91// c00 => s: 0 diff: +0 00% l 0 cached: 0 0; id 0
92// c01 => s: 32 diff: +32 00% l 5 cached: 64 2048; id 1
93// c02 => s: 64 diff: +32 100% l 6 cached: 64 4096; id 2
94// c03 => s: 96 diff: +32 50% l 6 cached: 64 6144; id 3
95// c04 => s: 128 diff: +32 33% l 7 cached: 64 8192; id 4
96// c05 => s: 160 diff: +32 25% l 7 cached: 64 10240; id 5
97// c06 => s: 192 diff: +32 20% l 7 cached: 64 12288; id 6
98// c07 => s: 224 diff: +32 16% l 7 cached: 64 14336; id 7
99// c08 => s: 256 diff: +32 14% l 8 cached: 64 16384; id 8
100// c09 => s: 384 diff: +128 50% l 8 cached: 42 16128; id 9
101// c10 => s: 512 diff: +128 33% l 9 cached: 32 16384; id 10
102// c11 => s: 768 diff: +256 50% l 9 cached: 21 16128; id 11
103// c12 => s: 1024 diff: +256 33% l 10 cached: 16 16384; id 12
104// c13 => s: 1536 diff: +512 50% l 10 cached: 10 15360; id 13
105// c14 => s: 2048 diff: +512 33% l 11 cached: 8 16384; id 14
106// c15 => s: 3072 diff: +1024 50% l 11 cached: 5 15360; id 15
107// c16 => s: 4096 diff: +1024 33% l 12 cached: 4 16384; id 16
108// c17 => s: 6144 diff: +2048 50% l 12 cached: 2 12288; id 17
109// c18 => s: 8192 diff: +2048 33% l 13 cached: 2 16384; id 18
110// c19 => s: 12288 diff: +4096 50% l 13 cached: 1 12288; id 19
111// c20 => s: 16384 diff: +4096 33% l 14 cached: 1 16384; id 20
112// c21 => s: 24576 diff: +8192 50% l 14 cached: 1 24576; id 21
113// c22 => s: 32768 diff: +8192 33% l 15 cached: 1 32768; id 22
114// c23 => s: 49152 diff: +16384 50% l 15 cached: 1 49152; id 23
115// c24 => s: 65536 diff: +16384 33% l 16 cached: 1 65536; id 24
116// c25 => s: 98304 diff: +32768 50% l 16 cached: 1 98304; id 25
117// c26 => s: 131072 diff: +32768 33% l 17 cached: 1 131072; id 26
118
119template <uptr kNumBits, uptr kMinSizeLog, uptr kMidSizeLog, uptr kMaxSizeLog,
120 uptr kMaxNumCachedHintT, uptr kMaxBytesCachedLog>
121class SizeClassMap {
122 static const uptr kMinSize = 1 << kMinSizeLog;
123 static const uptr kMidSize = 1 << kMidSizeLog;
124 static const uptr kMidClass = kMidSize / kMinSize;
125 static const uptr S = kNumBits - 1;
126 static const uptr M = (1 << S) - 1;
127
128 public:
129 // kMaxNumCachedHintT is a power of two. It serves as a hint
130 // for the size of TransferBatch, the actual size could be a bit smaller.
131 static const uptr kMaxNumCachedHint = kMaxNumCachedHintT;
132 COMPILER_CHECK((kMaxNumCachedHint & (kMaxNumCachedHint - 1)) == 0);
133
134 static const uptr kMaxSize = 1UL << kMaxSizeLog;
135 static const uptr kNumClasses =
136 kMidClass + ((kMaxSizeLog - kMidSizeLog) << S) + 1 + 1;
137 static const uptr kLargestClassID = kNumClasses - 2;
138 static const uptr kBatchClassID = kNumClasses - 1;
139 COMPILER_CHECK(kNumClasses >= 16 && kNumClasses <= 256);
140 static const uptr kNumClassesRounded =
141 kNumClasses <= 32 ? 32 :
142 kNumClasses <= 64 ? 64 :
143 kNumClasses <= 128 ? 128 : 256;
144
145 static uptr Size(uptr class_id) {
146 // Estimate the result for kBatchClassID because this class does not know
147 // the exact size of TransferBatch. It's OK since we are using the actual
148 // sizeof(TransferBatch) where it matters.
149 if (UNLIKELY(class_id == kBatchClassID))
150 return kMaxNumCachedHint * sizeof(uptr);
151 if (class_id <= kMidClass)
152 return kMinSize * class_id;
153 class_id -= kMidClass;
154 uptr t = kMidSize << (class_id >> S);
155 return t + (t >> S) * (class_id & M);
156 }
157
158 static uptr ClassID(uptr size) {
159 if (UNLIKELY(size > kMaxSize))
160 return 0;
161 if (size <= kMidSize)
162 return (size + kMinSize - 1) >> kMinSizeLog;
163 const uptr l = MostSignificantSetBitIndex(size);
164 const uptr hbits = (size >> (l - S)) & M;
165 const uptr lbits = size & ((1U << (l - S)) - 1);
166 const uptr l1 = l - kMidSizeLog;
167 return kMidClass + (l1 << S) + hbits + (lbits > 0);
168 }
169
170 static uptr MaxCachedHint(uptr size) {
171 DCHECK_LE(size, kMaxSize);
172 if (UNLIKELY(size == 0))
173 return 0;
174 uptr n;
175 // Force a 32-bit division if the template parameters allow for it.
176 if (kMaxBytesCachedLog > 31 || kMaxSizeLog > 31)
177 n = (1UL << kMaxBytesCachedLog) / size;
178 else
179 n = (1U << kMaxBytesCachedLog) / static_cast<u32>(size);
180 return Max<uptr>(1U, Min(kMaxNumCachedHint, n));
181 }
182
183 static void Print() {
184 uptr prev_s = 0;
185 uptr total_cached = 0;
186 for (uptr i = 0; i < kNumClasses; i++) {
187 uptr s = Size(i);
188 if (s >= kMidSize / 2 && (s & (s - 1)) == 0)
189 Printf("\n");
190 uptr d = s - prev_s;
191 uptr p = prev_s ? (d * 100 / prev_s) : 0;
192 uptr l = s ? MostSignificantSetBitIndex(s) : 0;
193 uptr cached = MaxCachedHint(s) * s;
194 if (i == kBatchClassID)
195 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));
199 total_cached += cached;
200 prev_s = s;
201 }
202 Printf("Total cached: %zd\n", total_cached);
203 }
204
205 static void Validate() {
206 for (uptr c = 1; c < kNumClasses; c++) {
207 // Printf("Validate: c%zd\n", c);
208 uptr s = Size(c);
209 CHECK_NE(s, 0U);
210 if (c == kBatchClassID)
211 continue;
212 CHECK_EQ(ClassID(s), c);
213 if (c < kLargestClassID)
214 CHECK_EQ(ClassID(s + 1), c + 1);
215 CHECK_EQ(ClassID(s - 1), c);
216 CHECK_GT(Size(c), Size(c - 1));
217 }
218 CHECK_EQ(ClassID(kMaxSize + 1), 0);
219
220 for (uptr s = 1; s <= kMaxSize; s++) {
221 uptr c = ClassID(s);
222 // Printf("s%zd => c%zd\n", s, c);
223 CHECK_LT(c, kNumClasses);
224 CHECK_GE(Size(c), s);
225 if (c > 0)
226 CHECK_LT(Size(c - 1), s);
227 }
228 }
229};
230
231typedef SizeClassMap<3, 4, 8, 17, 128, 16> DefaultSizeClassMap;
232typedef SizeClassMap<3, 4, 8, 17, 64, 14> CompactSizeClassMap;
233typedef SizeClassMap<2, 5, 9, 16, 64, 14> VeryCompactSizeClassMap;
234
235// The following SizeClassMap only holds a way small number of cached entries,
236// allowing for denser per-class arrays, smaller memory footprint and usually
237// better performances in threaded environments.
238typedef SizeClassMap<3, 4, 8, 17, 8, 10> DenseSizeClassMap;
239// Similar to VeryCompact map above, this one has a small number of different
240// size classes, and also reduced thread-local caches.
241typedef SizeClassMap<2, 5, 9, 16, 8, 10> VeryDenseSizeClassMap;
lib/tsan/sanitizer_common/sanitizer_allocator_stats.h created+106
...@@ -0,0 +1,106 @@
1//===-- sanitizer_allocator_stats.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// Memory allocator statistics
17enum AllocatorStat {
18 AllocatorStatAllocated,
19 AllocatorStatMapped,
20 AllocatorStatCount
21};
22
23typedef uptr AllocatorStatCounters[AllocatorStatCount];
24
25// Per-thread stats, live in per-thread cache.
26class AllocatorStats {
27 public:
28 void Init() {
29 internal_memset(this, 0, sizeof(*this));
30 }
31 void InitLinkerInitialized() {}
32
33 void Add(AllocatorStat i, uptr v) {
34 v += atomic_load(&stats_[i], memory_order_relaxed);
35 atomic_store(&stats_[i], v, memory_order_relaxed);
36 }
37
38 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);
41 }
42
43 void Set(AllocatorStat i, uptr v) {
44 atomic_store(&stats_[i], v, memory_order_relaxed);
45 }
46
47 uptr Get(AllocatorStat i) const {
48 return atomic_load(&stats_[i], memory_order_relaxed);
49 }
50
51 private:
52 friend class AllocatorGlobalStats;
53 AllocatorStats *next_;
54 AllocatorStats *prev_;
55 atomic_uintptr_t stats_[AllocatorStatCount];
56};
57
58// Global stats, used for aggregation and querying.
59class AllocatorGlobalStats : public AllocatorStats {
60 public:
61 void InitLinkerInitialized() {
62 next_ = this;
63 prev_ = this;
64 }
65 void Init() {
66 internal_memset(this, 0, sizeof(*this));
67 InitLinkerInitialized();
68 }
69
70 void Register(AllocatorStats *s) {
71 SpinMutexLock l(&mu_);
72 s->next_ = next_;
73 s->prev_ = this;
74 next_->prev_ = s;
75 next_ = s;
76 }
77
78 void Unregister(AllocatorStats *s) {
79 SpinMutexLock l(&mu_);
80 s->prev_->next_ = s->next_;
81 s->next_->prev_ = s->prev_;
82 for (int i = 0; i < AllocatorStatCount; i++)
83 Add(AllocatorStat(i), s->Get(AllocatorStat(i)));
84 }
85
86 void Get(AllocatorStatCounters s) const {
87 internal_memset(s, 0, AllocatorStatCount * sizeof(uptr));
88 SpinMutexLock l(&mu_);
89 const AllocatorStats *stats = this;
90 for (;;) {
91 for (int i = 0; i < AllocatorStatCount; i++)
92 s[i] += stats->Get(AllocatorStat(i));
93 stats = stats->next_;
94 if (stats == this)
95 break;
96 }
97 // All stats must be non-negative.
98 for (int i = 0; i < AllocatorStatCount; i++)
99 s[i] = ((sptr)s[i]) >= 0 ? s[i] : 0;
100 }
101
102 private:
103 mutable StaticSpinMutex mu_;
104};
105
106
lib/tsan/sanitizer_common/sanitizer_asm.h created+68
...@@ -0,0 +1,68 @@
1//===-- sanitizer_asm.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// Various support for assemebler.
10//
11//===----------------------------------------------------------------------===//
12
13// Some toolchains do not support .cfi asm directives, so we have to hide
14// them inside macros.
15#if defined(__clang__) || \
16 (defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM))
17 // GCC defined __GCC_HAVE_DWARF2_CFI_ASM if it supports CFI.
18 // Clang seems to support CFI by default (or not?).
19 // We need two versions of macros: for inline asm and standalone asm files.
20# define CFI_INL_ADJUST_CFA_OFFSET(n) ".cfi_adjust_cfa_offset " #n ";"
21
22# define CFI_STARTPROC .cfi_startproc
23# define CFI_ENDPROC .cfi_endproc
24# define CFI_ADJUST_CFA_OFFSET(n) .cfi_adjust_cfa_offset n
25# define CFI_DEF_CFA_OFFSET(n) .cfi_def_cfa_offset n
26# define CFI_REL_OFFSET(reg, n) .cfi_rel_offset reg, n
27# define CFI_OFFSET(reg, n) .cfi_offset reg, n
28# define CFI_DEF_CFA_REGISTER(reg) .cfi_def_cfa_register reg
29# define CFI_DEF_CFA(reg, n) .cfi_def_cfa reg, n
30# define CFI_RESTORE(reg) .cfi_restore reg
31
32#else // No CFI
33# define CFI_INL_ADJUST_CFA_OFFSET(n)
34# define CFI_STARTPROC
35# define CFI_ENDPROC
36# define CFI_ADJUST_CFA_OFFSET(n)
37# define CFI_DEF_CFA_OFFSET(n)
38# define CFI_REL_OFFSET(reg, n)
39# define CFI_OFFSET(reg, n)
40# define CFI_DEF_CFA_REGISTER(reg)
41# define CFI_DEF_CFA(reg, n)
42# define CFI_RESTORE(reg)
43#endif
44
45#if !defined(__APPLE__)
46# define ASM_HIDDEN(symbol) .hidden symbol
47# define ASM_TYPE_FUNCTION(symbol) .type symbol, %function
48# define ASM_SIZE(symbol) .size symbol, .-symbol
49# define ASM_SYMBOL(symbol) symbol
50# define ASM_SYMBOL_INTERCEPTOR(symbol) symbol
51# define ASM_WRAPPER_NAME(symbol) __interceptor_##symbol
52#else
53# define ASM_HIDDEN(symbol)
54# define ASM_TYPE_FUNCTION(symbol)
55# define ASM_SIZE(symbol)
56# define ASM_SYMBOL(symbol) _##symbol
57# define ASM_SYMBOL_INTERCEPTOR(symbol) _wrap_##symbol
58# define ASM_WRAPPER_NAME(symbol) __interceptor_##symbol
59#endif
60
61#if defined(__ELF__) && (defined(__GNU__) || defined(__FreeBSD__) || \
62 defined(__Fuchsia__) || defined(__linux__))
63// clang-format off
64#define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits // NOLINT
65// clang-format on
66#else
67#define NO_EXEC_STACK_DIRECTIVE
68#endif
lib/tsan/sanitizer_common/sanitizer_atomic.h created+86
...@@ -0,0 +1,86 @@
1//===-- sanitizer_atomic.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/AddressSanitizer runtime.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef SANITIZER_ATOMIC_H
14#define SANITIZER_ATOMIC_H
15
16#include "sanitizer_internal_defs.h"
17
18namespace __sanitizer {
19
20enum memory_order {
21 memory_order_relaxed = 1 << 0,
22 memory_order_consume = 1 << 1,
23 memory_order_acquire = 1 << 2,
24 memory_order_release = 1 << 3,
25 memory_order_acq_rel = 1 << 4,
26 memory_order_seq_cst = 1 << 5
27};
28
29struct atomic_uint8_t {
30 typedef u8 Type;
31 volatile Type val_dont_use;
32};
33
34struct atomic_uint16_t {
35 typedef u16 Type;
36 volatile Type val_dont_use;
37};
38
39struct atomic_sint32_t {
40 typedef s32 Type;
41 volatile Type val_dont_use;
42};
43
44struct atomic_uint32_t {
45 typedef u32 Type;
46 volatile Type val_dont_use;
47};
48
49struct atomic_uint64_t {
50 typedef u64 Type;
51 // On 32-bit platforms u64 is not necessary aligned on 8 bytes.
52 volatile ALIGNED(8) Type val_dont_use;
53};
54
55struct atomic_uintptr_t {
56 typedef uptr Type;
57 volatile Type val_dont_use;
58};
59
60} // namespace __sanitizer
61
62#if defined(__clang__) || defined(__GNUC__)
63# include "sanitizer_atomic_clang.h"
64#elif defined(_MSC_VER)
65# include "sanitizer_atomic_msvc.h"
66#else
67# error "Unsupported compiler"
68#endif
69
70namespace __sanitizer {
71
72// Clutter-reducing helpers.
73
74template<typename T>
75INLINE typename T::Type atomic_load_relaxed(const volatile T *a) {
76 return atomic_load(a, memory_order_relaxed);
77}
78
79template<typename T>
80INLINE void atomic_store_relaxed(volatile T *a, typename T::Type v) {
81 atomic_store(a, v, memory_order_relaxed);
82}
83
84} // namespace __sanitizer
85
86#endif // SANITIZER_ATOMIC_H
lib/tsan/sanitizer_common/sanitizer_atomic_clang.h created+105
...@@ -0,0 +1,105 @@
1//===-- sanitizer_atomic_clang.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/AddressSanitizer runtime.
10// Not intended for direct inclusion. Include sanitizer_atomic.h.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef SANITIZER_ATOMIC_CLANG_H
15#define SANITIZER_ATOMIC_CLANG_H
16
17#if defined(__i386__) || defined(__x86_64__)
18# include "sanitizer_atomic_clang_x86.h"
19#else
20# include "sanitizer_atomic_clang_other.h"
21#endif
22
23namespace __sanitizer {
24
25// We would like to just use compiler builtin atomic operations
26// for loads and stores, but they are mostly broken in clang:
27// - they lead to vastly inefficient code generation
28// (http://llvm.org/bugs/show_bug.cgi?id=17281)
29// - 64-bit atomic operations are not implemented on x86_32
30// (http://llvm.org/bugs/show_bug.cgi?id=15034)
31// - they are not implemented on ARM
32// error: undefined reference to '__atomic_load_4'
33
34// See http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html
35// for mappings of the memory model to different processors.
36
37INLINE void atomic_signal_fence(memory_order) {
38 __asm__ __volatile__("" ::: "memory");
39}
40
41INLINE void atomic_thread_fence(memory_order) {
42 __sync_synchronize();
43}
44
45template<typename T>
46INLINE typename T::Type atomic_fetch_add(volatile T *a,
47 typename T::Type v, memory_order mo) {
48 (void)mo;
49 DCHECK(!((uptr)a % sizeof(*a)));
50 return __sync_fetch_and_add(&a->val_dont_use, v);
51}
52
53template<typename T>
54INLINE typename T::Type atomic_fetch_sub(volatile T *a,
55 typename T::Type v, memory_order mo) {
56 (void)mo;
57 DCHECK(!((uptr)a % sizeof(*a)));
58 return __sync_fetch_and_add(&a->val_dont_use, -v);
59}
60
61template<typename T>
62INLINE typename T::Type atomic_exchange(volatile T *a,
63 typename T::Type v, memory_order mo) {
64 DCHECK(!((uptr)a % sizeof(*a)));
65 if (mo & (memory_order_release | memory_order_acq_rel | memory_order_seq_cst))
66 __sync_synchronize();
67 v = __sync_lock_test_and_set(&a->val_dont_use, v);
68 if (mo == memory_order_seq_cst)
69 __sync_synchronize();
70 return v;
71}
72
73template <typename T>
74INLINE bool atomic_compare_exchange_strong(volatile T *a, typename T::Type *cmp,
75 typename T::Type xchg,
76 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;
84}
85
86template<typename T>
87INLINE bool atomic_compare_exchange_weak(volatile T *a,
88 typename T::Type *cmp,
89 typename T::Type xchg,
90 memory_order mo) {
91 return atomic_compare_exchange_strong(a, cmp, xchg, mo);
92}
93
94} // namespace __sanitizer
95
96// This include provides explicit template instantiations for atomic_uint64_t
97// on MIPS32, which does not directly support 8 byte atomics. It has to
98// proceed the template definitions above.
99#if defined(_MIPS_SIM) && defined(_ABIO32)
100 #include "sanitizer_atomic_clang_mips.h"
101#endif
102
103#undef ATOMIC_ORDER
104
105#endif // SANITIZER_ATOMIC_CLANG_H
lib/tsan/sanitizer_common/sanitizer_atomic_clang_mips.h created+117
...@@ -0,0 +1,117 @@
1//===-- sanitizer_atomic_clang_mips.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/AddressSanitizer runtime.
10// Not intended for direct inclusion. Include sanitizer_atomic.h.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef SANITIZER_ATOMIC_CLANG_MIPS_H
15#define SANITIZER_ATOMIC_CLANG_MIPS_H
16
17namespace __sanitizer {
18
19// MIPS32 does not support atomics > 4 bytes. To address this lack of
20// functionality, the sanitizer library provides helper methods which use an
21// internal spin lock mechanism to emulate atomic oprations when the size is
22// 8 bytes.
23static void __spin_lock(volatile int *lock) {
24 while (__sync_lock_test_and_set(lock, 1))
25 while (*lock) {
26 }
27}
28
29static void __spin_unlock(volatile int *lock) { __sync_lock_release(lock); }
30
31// Make sure the lock is on its own cache line to prevent false sharing.
32// Put it inside a struct that is aligned and padded to the typical MIPS
33// cacheline which is 32 bytes.
34static struct {
35 int lock;
36 char pad[32 - sizeof(int)];
37} __attribute__((aligned(32))) lock = {0, {0}};
38
39template <>
40INLINE atomic_uint64_t::Type atomic_fetch_add(volatile atomic_uint64_t *ptr,
41 atomic_uint64_t::Type val,
42 memory_order mo) {
43 DCHECK(mo &
44 (memory_order_relaxed | memory_order_releasae | memory_order_seq_cst));
45 DCHECK(!((uptr)ptr % sizeof(*ptr)));
46
47 atomic_uint64_t::Type ret;
48
49 __spin_lock(&lock.lock);
50 ret = *(const_cast<atomic_uint64_t::Type volatile *>(&ptr->val_dont_use));
51 ptr->val_dont_use = ret + val;
52 __spin_unlock(&lock.lock);
53
54 return ret;
55}
56
57template <>
58INLINE atomic_uint64_t::Type atomic_fetch_sub(volatile atomic_uint64_t *ptr,
59 atomic_uint64_t::Type val,
60 memory_order mo) {
61 return atomic_fetch_add(ptr, -val, mo);
62}
63
64template <>
65INLINE bool atomic_compare_exchange_strong(volatile atomic_uint64_t *ptr,
66 atomic_uint64_t::Type *cmp,
67 atomic_uint64_t::Type xchg,
68 memory_order mo) {
69 DCHECK(mo &
70 (memory_order_relaxed | memory_order_releasae | memory_order_seq_cst));
71 DCHECK(!((uptr)ptr % sizeof(*ptr)));
72
73 typedef atomic_uint64_t::Type Type;
74 Type cmpv = *cmp;
75 Type prev;
76 bool ret = false;
77
78 __spin_lock(&lock.lock);
79 prev = *(const_cast<Type volatile *>(&ptr->val_dont_use));
80 if (prev == cmpv) {
81 ret = true;
82 ptr->val_dont_use = xchg;
83 }
84 __spin_unlock(&lock.lock);
85
86 return ret;
87}
88
89template <>
90INLINE atomic_uint64_t::Type atomic_load(const volatile atomic_uint64_t *ptr,
91 memory_order mo) {
92 DCHECK(mo &
93 (memory_order_relaxed | memory_order_releasae | memory_order_seq_cst));
94 DCHECK(!((uptr)ptr % sizeof(*ptr)));
95
96 atomic_uint64_t::Type zero = 0;
97 volatile atomic_uint64_t *Newptr =
98 const_cast<volatile atomic_uint64_t *>(ptr);
99 return atomic_fetch_add(Newptr, zero, mo);
100}
101
102template <>
103INLINE void atomic_store(volatile atomic_uint64_t *ptr, atomic_uint64_t::Type v,
104 memory_order mo) {
105 DCHECK(mo &
106 (memory_order_relaxed | memory_order_releasae | memory_order_seq_cst));
107 DCHECK(!((uptr)ptr % sizeof(*ptr)));
108
109 __spin_lock(&lock.lock);
110 ptr->val_dont_use = v;
111 __spin_unlock(&lock.lock);
112}
113
114} // namespace __sanitizer
115
116#endif // SANITIZER_ATOMIC_CLANG_MIPS_H
117
lib/tsan/sanitizer_common/sanitizer_atomic_clang_other.h created+97
...@@ -0,0 +1,97 @@
1//===-- sanitizer_atomic_clang_other.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/AddressSanitizer runtime.
10// Not intended for direct inclusion. Include sanitizer_atomic.h.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef SANITIZER_ATOMIC_CLANG_OTHER_H
15#define SANITIZER_ATOMIC_CLANG_OTHER_H
16
17namespace __sanitizer {
18
19
20INLINE void proc_yield(int cnt) {
21 __asm__ __volatile__("" ::: "memory");
22}
23
24template<typename T>
25INLINE typename T::Type atomic_load(
26 const volatile T *a, memory_order mo) {
27 DCHECK(mo & (memory_order_relaxed | memory_order_consume
28 | memory_order_acquire | memory_order_seq_cst));
29 DCHECK(!((uptr)a % sizeof(*a)));
30 typename T::Type v;
31
32 if (sizeof(*a) < 8 || sizeof(void*) == 8) {
33 // Assume that aligned loads are atomic.
34 if (mo == memory_order_relaxed) {
35 v = a->val_dont_use;
36 } else if (mo == memory_order_consume) {
37 // Assume that processor respects data dependencies
38 // (and that compiler won't break them).
39 __asm__ __volatile__("" ::: "memory");
40 v = a->val_dont_use;
41 __asm__ __volatile__("" ::: "memory");
42 } else if (mo == memory_order_acquire) {
43 __asm__ __volatile__("" ::: "memory");
44 v = a->val_dont_use;
45 __sync_synchronize();
46 } else { // seq_cst
47 // E.g. on POWER we need a hw fence even before the store.
48 __sync_synchronize();
49 v = a->val_dont_use;
50 __sync_synchronize();
51 }
52 } else {
53 // 64-bit load on 32-bit platform.
54 // Gross, but simple and reliable.
55 // Assume that it is not in read-only memory.
56 v = __sync_fetch_and_add(
57 const_cast<typename T::Type volatile *>(&a->val_dont_use), 0);
58 }
59 return v;
60}
61
62template<typename T>
63INLINE void atomic_store(volatile T *a, typename T::Type v, memory_order mo) {
64 DCHECK(mo & (memory_order_relaxed | memory_order_release
65 | memory_order_seq_cst));
66 DCHECK(!((uptr)a % sizeof(*a)));
67
68 if (sizeof(*a) < 8 || sizeof(void*) == 8) {
69 // Assume that aligned loads are atomic.
70 if (mo == memory_order_relaxed) {
71 a->val_dont_use = v;
72 } else if (mo == memory_order_release) {
73 __sync_synchronize();
74 a->val_dont_use = v;
75 __asm__ __volatile__("" ::: "memory");
76 } else { // seq_cst
77 __sync_synchronize();
78 a->val_dont_use = v;
79 __sync_synchronize();
80 }
81 } else {
82 // 64-bit store on 32-bit platform.
83 // Gross, but simple and reliable.
84 typename T::Type cmp = a->val_dont_use;
85 typename T::Type cur;
86 for (;;) {
87 cur = __sync_val_compare_and_swap(&a->val_dont_use, cmp, v);
88 if (cur == cmp || cur == v)
89 break;
90 cmp = cur;
91 }
92 }
93}
94
95} // namespace __sanitizer
96
97#endif // #ifndef SANITIZER_ATOMIC_CLANG_OTHER_H
lib/tsan/sanitizer_common/sanitizer_atomic_clang_x86.h created+113
...@@ -0,0 +1,113 @@
1//===-- sanitizer_atomic_clang_x86.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/AddressSanitizer runtime.
10// Not intended for direct inclusion. Include sanitizer_atomic.h.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef SANITIZER_ATOMIC_CLANG_X86_H
15#define SANITIZER_ATOMIC_CLANG_X86_H
16
17namespace __sanitizer {
18
19INLINE void proc_yield(int cnt) {
20 __asm__ __volatile__("" ::: "memory");
21 for (int i = 0; i < cnt; i++)
22 __asm__ __volatile__("pause");
23 __asm__ __volatile__("" ::: "memory");
24}
25
26template<typename T>
27INLINE typename T::Type atomic_load(
28 const volatile T *a, memory_order mo) {
29 DCHECK(mo & (memory_order_relaxed | memory_order_consume
30 | memory_order_acquire | memory_order_seq_cst));
31 DCHECK(!((uptr)a % sizeof(*a)));
32 typename T::Type v;
33
34 if (sizeof(*a) < 8 || sizeof(void*) == 8) {
35 // Assume that aligned loads are atomic.
36 if (mo == memory_order_relaxed) {
37 v = a->val_dont_use;
38 } else if (mo == memory_order_consume) {
39 // Assume that processor respects data dependencies
40 // (and that compiler won't break them).
41 __asm__ __volatile__("" ::: "memory");
42 v = a->val_dont_use;
43 __asm__ __volatile__("" ::: "memory");
44 } else if (mo == memory_order_acquire) {
45 __asm__ __volatile__("" ::: "memory");
46 v = a->val_dont_use;
47 // On x86 loads are implicitly acquire.
48 __asm__ __volatile__("" ::: "memory");
49 } else { // seq_cst
50 // On x86 plain MOV is enough for seq_cst store.
51 __asm__ __volatile__("" ::: "memory");
52 v = a->val_dont_use;
53 __asm__ __volatile__("" ::: "memory");
54 }
55 } else {
56 // 64-bit load on 32-bit platform.
57 __asm__ __volatile__(
58 "movq %1, %%mm0;" // Use mmx reg for 64-bit atomic moves
59 "movq %%mm0, %0;" // (ptr could be read-only)
60 "emms;" // Empty mmx state/Reset FP regs
61 : "=m" (v)
62 : "m" (a->val_dont_use)
63 : // mark the mmx registers as clobbered
64#ifdef __MMX__
65 "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7",
66#endif // #ifdef __MMX__
67 "memory");
68 }
69 return v;
70}
71
72template<typename T>
73INLINE void atomic_store(volatile T *a, typename T::Type v, memory_order mo) {
74 DCHECK(mo & (memory_order_relaxed | memory_order_release
75 | memory_order_seq_cst));
76 DCHECK(!((uptr)a % sizeof(*a)));
77
78 if (sizeof(*a) < 8 || sizeof(void*) == 8) {
79 // Assume that aligned loads are atomic.
80 if (mo == memory_order_relaxed) {
81 a->val_dont_use = v;
82 } else if (mo == memory_order_release) {
83 // On x86 stores are implicitly release.
84 __asm__ __volatile__("" ::: "memory");
85 a->val_dont_use = v;
86 __asm__ __volatile__("" ::: "memory");
87 } else { // seq_cst
88 // On x86 stores are implicitly release.
89 __asm__ __volatile__("" ::: "memory");
90 a->val_dont_use = v;
91 __sync_synchronize();
92 }
93 } else {
94 // 64-bit store on 32-bit platform.
95 __asm__ __volatile__(
96 "movq %1, %%mm0;" // Use mmx reg for 64-bit atomic moves
97 "movq %%mm0, %0;"
98 "emms;" // Empty mmx state/Reset FP regs
99 : "=m" (a->val_dont_use)
100 : "m" (v)
101 : // mark the mmx registers as clobbered
102#ifdef __MMX__
103 "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7",
104#endif // #ifdef __MMX__
105 "memory");
106 if (mo == memory_order_seq_cst)
107 __sync_synchronize();
108 }
109}
110
111} // namespace __sanitizer
112
113#endif // #ifndef SANITIZER_ATOMIC_CLANG_X86_H
lib/tsan/sanitizer_common/sanitizer_atomic_msvc.h created+256
...@@ -0,0 +1,256 @@
1//===-- sanitizer_atomic_msvc.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/AddressSanitizer runtime.
10// Not intended for direct inclusion. Include sanitizer_atomic.h.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef SANITIZER_ATOMIC_MSVC_H
15#define SANITIZER_ATOMIC_MSVC_H
16
17extern "C" void _ReadWriteBarrier();
18#pragma intrinsic(_ReadWriteBarrier)
19extern "C" void _mm_mfence();
20#pragma intrinsic(_mm_mfence)
21extern "C" void _mm_pause();
22#pragma intrinsic(_mm_pause)
23extern "C" char _InterlockedExchange8(char volatile *Addend, char Value);
24#pragma intrinsic(_InterlockedExchange8)
25extern "C" short _InterlockedExchange16(short volatile *Addend, short Value);
26#pragma intrinsic(_InterlockedExchange16)
27extern "C" long _InterlockedExchange(long volatile *Addend, long Value);
28#pragma intrinsic(_InterlockedExchange)
29extern "C" long _InterlockedExchangeAdd(long volatile *Addend, long Value);
30#pragma intrinsic(_InterlockedExchangeAdd)
31extern "C" char _InterlockedCompareExchange8(char volatile *Destination,
32 char Exchange, char Comparand);
33#pragma intrinsic(_InterlockedCompareExchange8)
34extern "C" short _InterlockedCompareExchange16(short volatile *Destination,
35 short Exchange, short Comparand);
36#pragma intrinsic(_InterlockedCompareExchange16)
37extern "C" long long _InterlockedCompareExchange64(
38 long long volatile *Destination, long long Exchange, long long Comparand);
39#pragma intrinsic(_InterlockedCompareExchange64)
40extern "C" void *_InterlockedCompareExchangePointer(
41 void *volatile *Destination,
42 void *Exchange, void *Comparand);
43#pragma intrinsic(_InterlockedCompareExchangePointer)
44extern "C" long __cdecl _InterlockedCompareExchange(long volatile *Destination,
45 long Exchange,
46 long Comparand);
47#pragma intrinsic(_InterlockedCompareExchange)
48
49#ifdef _WIN64
50extern "C" long long _InterlockedExchangeAdd64(long long volatile *Addend,
51 long long Value);
52#pragma intrinsic(_InterlockedExchangeAdd64)
53#endif
54
55namespace __sanitizer {
56
57INLINE void atomic_signal_fence(memory_order) {
58 _ReadWriteBarrier();
59}
60
61INLINE void atomic_thread_fence(memory_order) {
62 _mm_mfence();
63}
64
65INLINE void proc_yield(int cnt) {
66 for (int i = 0; i < cnt; i++)
67 _mm_pause();
68}
69
70template<typename T>
71INLINE typename T::Type atomic_load(
72 const volatile T *a, memory_order mo) {
73 DCHECK(mo & (memory_order_relaxed | memory_order_consume
74 | memory_order_acquire | memory_order_seq_cst));
75 DCHECK(!((uptr)a % sizeof(*a)));
76 typename T::Type v;
77 // FIXME(dvyukov): 64-bit load is not atomic on 32-bits.
78 if (mo == memory_order_relaxed) {
79 v = a->val_dont_use;
80 } else {
81 atomic_signal_fence(memory_order_seq_cst);
82 v = a->val_dont_use;
83 atomic_signal_fence(memory_order_seq_cst);
84 }
85 return v;
86}
87
88template<typename T>
89INLINE void atomic_store(volatile T *a, typename T::Type v, memory_order mo) {
90 DCHECK(mo & (memory_order_relaxed | memory_order_release
91 | memory_order_seq_cst));
92 DCHECK(!((uptr)a % sizeof(*a)));
93 // FIXME(dvyukov): 64-bit store is not atomic on 32-bits.
94 if (mo == memory_order_relaxed) {
95 a->val_dont_use = v;
96 } else {
97 atomic_signal_fence(memory_order_seq_cst);
98 a->val_dont_use = v;
99 atomic_signal_fence(memory_order_seq_cst);
100 }
101 if (mo == memory_order_seq_cst)
102 atomic_thread_fence(memory_order_seq_cst);
103}
104
105INLINE u32 atomic_fetch_add(volatile atomic_uint32_t *a,
106 u32 v, memory_order mo) {
107 (void)mo;
108 DCHECK(!((uptr)a % sizeof(*a)));
109 return (u32)_InterlockedExchangeAdd((volatile long *)&a->val_dont_use,
110 (long)v);
111}
112
113INLINE uptr atomic_fetch_add(volatile atomic_uintptr_t *a,
114 uptr v, memory_order mo) {
115 (void)mo;
116 DCHECK(!((uptr)a % sizeof(*a)));
117#ifdef _WIN64
118 return (uptr)_InterlockedExchangeAdd64((volatile long long *)&a->val_dont_use,
119 (long long)v);
120#else
121 return (uptr)_InterlockedExchangeAdd((volatile long *)&a->val_dont_use,
122 (long)v);
123#endif
124}
125
126INLINE u32 atomic_fetch_sub(volatile atomic_uint32_t *a,
127 u32 v, memory_order mo) {
128 (void)mo;
129 DCHECK(!((uptr)a % sizeof(*a)));
130 return (u32)_InterlockedExchangeAdd((volatile long *)&a->val_dont_use,
131 -(long)v);
132}
133
134INLINE uptr atomic_fetch_sub(volatile atomic_uintptr_t *a,
135 uptr v, memory_order mo) {
136 (void)mo;
137 DCHECK(!((uptr)a % sizeof(*a)));
138#ifdef _WIN64
139 return (uptr)_InterlockedExchangeAdd64((volatile long long *)&a->val_dont_use,
140 -(long long)v);
141#else
142 return (uptr)_InterlockedExchangeAdd((volatile long *)&a->val_dont_use,
143 -(long)v);
144#endif
145}
146
147INLINE u8 atomic_exchange(volatile atomic_uint8_t *a,
148 u8 v, memory_order mo) {
149 (void)mo;
150 DCHECK(!((uptr)a % sizeof(*a)));
151 return (u8)_InterlockedExchange8((volatile char*)&a->val_dont_use, v);
152}
153
154INLINE u16 atomic_exchange(volatile atomic_uint16_t *a,
155 u16 v, memory_order mo) {
156 (void)mo;
157 DCHECK(!((uptr)a % sizeof(*a)));
158 return (u16)_InterlockedExchange16((volatile short*)&a->val_dont_use, v);
159}
160
161INLINE u32 atomic_exchange(volatile atomic_uint32_t *a,
162 u32 v, memory_order mo) {
163 (void)mo;
164 DCHECK(!((uptr)a % sizeof(*a)));
165 return (u32)_InterlockedExchange((volatile long*)&a->val_dont_use, v);
166}
167
168INLINE bool atomic_compare_exchange_strong(volatile atomic_uint8_t *a,
169 u8 *cmp,
170 u8 xchgv,
171 memory_order mo) {
172 (void)mo;
173 DCHECK(!((uptr)a % sizeof(*a)));
174 u8 cmpv = *cmp;
175#ifdef _WIN64
176 u8 prev = (u8)_InterlockedCompareExchange8(
177 (volatile char*)&a->val_dont_use, (char)xchgv, (char)cmpv);
178#else
179 u8 prev;
180 __asm {
181 mov al, cmpv
182 mov ecx, a
183 mov dl, xchgv
184 lock cmpxchg [ecx], dl
185 mov prev, al
186 }
187#endif
188 if (prev == cmpv)
189 return true;
190 *cmp = prev;
191 return false;
192}
193
194INLINE bool atomic_compare_exchange_strong(volatile atomic_uintptr_t *a,
195 uptr *cmp,
196 uptr xchg,
197 memory_order mo) {
198 uptr cmpv = *cmp;
199 uptr prev = (uptr)_InterlockedCompareExchangePointer(
200 (void*volatile*)&a->val_dont_use, (void*)xchg, (void*)cmpv);
201 if (prev == cmpv)
202 return true;
203 *cmp = prev;
204 return false;
205}
206
207INLINE bool atomic_compare_exchange_strong(volatile atomic_uint16_t *a,
208 u16 *cmp,
209 u16 xchg,
210 memory_order mo) {
211 u16 cmpv = *cmp;
212 u16 prev = (u16)_InterlockedCompareExchange16(
213 (volatile short*)&a->val_dont_use, (short)xchg, (short)cmpv);
214 if (prev == cmpv)
215 return true;
216 *cmp = prev;
217 return false;
218}
219
220INLINE bool atomic_compare_exchange_strong(volatile atomic_uint32_t *a,
221 u32 *cmp,
222 u32 xchg,
223 memory_order mo) {
224 u32 cmpv = *cmp;
225 u32 prev = (u32)_InterlockedCompareExchange(
226 (volatile long*)&a->val_dont_use, (long)xchg, (long)cmpv);
227 if (prev == cmpv)
228 return true;
229 *cmp = prev;
230 return false;
231}
232
233INLINE bool atomic_compare_exchange_strong(volatile atomic_uint64_t *a,
234 u64 *cmp,
235 u64 xchg,
236 memory_order mo) {
237 u64 cmpv = *cmp;
238 u64 prev = (u64)_InterlockedCompareExchange64(
239 (volatile long long*)&a->val_dont_use, (long long)xchg, (long long)cmpv);
240 if (prev == cmpv)
241 return true;
242 *cmp = prev;
243 return false;
244}
245
246template<typename T>
247INLINE bool atomic_compare_exchange_weak(volatile T *a,
248 typename T::Type *cmp,
249 typename T::Type xchg,
250 memory_order mo) {
251 return atomic_compare_exchange_strong(a, cmp, xchg, mo);
252}
253
254} // namespace __sanitizer
255
256#endif // SANITIZER_ATOMIC_CLANG_H
lib/tsan/sanitizer_common/sanitizer_bitvector.h created+350
...@@ -0,0 +1,350 @@
1//===-- sanitizer_bitvector.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// Specializer BitVector implementation.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef SANITIZER_BITVECTOR_H
14#define SANITIZER_BITVECTOR_H
15
16#include "sanitizer_common.h"
17
18namespace __sanitizer {
19
20// Fixed size bit vector based on a single basic integer.
21template <class basic_int_t = uptr>
22class BasicBitVector {
23 public:
24 enum SizeEnum : uptr { kSize = sizeof(basic_int_t) * 8 };
25
26 uptr size() const { return kSize; }
27 // No CTOR.
28 void clear() { bits_ = 0; }
29 void setAll() { bits_ = ~(basic_int_t)0; }
30 bool empty() const { return bits_ == 0; }
31
32 // Returns true if the bit has changed from 0 to 1.
33 bool setBit(uptr idx) {
34 basic_int_t old = bits_;
35 bits_ |= mask(idx);
36 return bits_ != old;
37 }
38
39 // Returns true if the bit has changed from 1 to 0.
40 bool clearBit(uptr idx) {
41 basic_int_t old = bits_;
42 bits_ &= ~mask(idx);
43 return bits_ != old;
44 }
45
46 bool getBit(uptr idx) const { return (bits_ & mask(idx)) != 0; }
47
48 uptr getAndClearFirstOne() {
49 CHECK(!empty());
50 uptr idx = LeastSignificantSetBitIndex(bits_);
51 clearBit(idx);
52 return idx;
53 }
54
55 // Do "this |= v" and return whether new bits have been added.
56 bool setUnion(const BasicBitVector &v) {
57 basic_int_t old = bits_;
58 bits_ |= v.bits_;
59 return bits_ != old;
60 }
61
62 // Do "this &= v" and return whether any bits have been removed.
63 bool setIntersection(const BasicBitVector &v) {
64 basic_int_t old = bits_;
65 bits_ &= v.bits_;
66 return bits_ != old;
67 }
68
69 // Do "this &= ~v" and return whether any bits have been removed.
70 bool setDifference(const BasicBitVector &v) {
71 basic_int_t old = bits_;
72 bits_ &= ~v.bits_;
73 return bits_ != old;
74 }
75
76 void copyFrom(const BasicBitVector &v) { bits_ = v.bits_; }
77
78 // Returns true if 'this' intersects with 'v'.
79 bool intersectsWith(const BasicBitVector &v) const {
80 return (bits_ & v.bits_) != 0;
81 }
82
83 // for (BasicBitVector<>::Iterator it(bv); it.hasNext();) {
84 // uptr idx = it.next();
85 // use(idx);
86 // }
87 class Iterator {
88 public:
89 Iterator() { }
90 explicit Iterator(const BasicBitVector &bv) : bv_(bv) {}
91 bool hasNext() const { return !bv_.empty(); }
92 uptr next() { return bv_.getAndClearFirstOne(); }
93 void clear() { bv_.clear(); }
94 private:
95 BasicBitVector bv_;
96 };
97
98 private:
99 basic_int_t mask(uptr idx) const {
100 CHECK_LT(idx, size());
101 return (basic_int_t)1UL << idx;
102 }
103 basic_int_t bits_;
104};
105
106// Fixed size bit vector of (kLevel1Size*BV::kSize**2) bits.
107// The implementation is optimized for better performance on
108// sparse bit vectors, i.e. the those with few set bits.
109template <uptr kLevel1Size = 1, class BV = BasicBitVector<> >
110class TwoLevelBitVector {
111 // This is essentially a 2-level bit vector.
112 // Set bit in the first level BV indicates that there are set bits
113 // in the corresponding BV of the second level.
114 // This structure allows O(kLevel1Size) time for clear() and empty(),
115 // as well fast handling of sparse BVs.
116 public:
117 enum SizeEnum : uptr { kSize = BV::kSize * BV::kSize * kLevel1Size };
118 // No CTOR.
119
120 uptr size() const { return kSize; }
121
122 void clear() {
123 for (uptr i = 0; i < kLevel1Size; i++)
124 l1_[i].clear();
125 }
126
127 void setAll() {
128 for (uptr i0 = 0; i0 < kLevel1Size; i0++) {
129 l1_[i0].setAll();
130 for (uptr i1 = 0; i1 < BV::kSize; i1++)
131 l2_[i0][i1].setAll();
132 }
133 }
134
135 bool empty() const {
136 for (uptr i = 0; i < kLevel1Size; i++)
137 if (!l1_[i].empty())
138 return false;
139 return true;
140 }
141
142 // Returns true if the bit has changed from 0 to 1.
143 bool setBit(uptr idx) {
144 check(idx);
145 uptr i0 = idx0(idx);
146 uptr i1 = idx1(idx);
147 uptr i2 = idx2(idx);
148 if (!l1_[i0].getBit(i1)) {
149 l1_[i0].setBit(i1);
150 l2_[i0][i1].clear();
151 }
152 bool res = l2_[i0][i1].setBit(i2);
153 // Printf("%s: %zd => %zd %zd %zd; %d\n", __func__,
154 // idx, i0, i1, i2, res);
155 return res;
156 }
157
158 bool clearBit(uptr idx) {
159 check(idx);
160 uptr i0 = idx0(idx);
161 uptr i1 = idx1(idx);
162 uptr i2 = idx2(idx);
163 bool res = false;
164 if (l1_[i0].getBit(i1)) {
165 res = l2_[i0][i1].clearBit(i2);
166 if (l2_[i0][i1].empty())
167 l1_[i0].clearBit(i1);
168 }
169 return res;
170 }
171
172 bool getBit(uptr idx) const {
173 check(idx);
174 uptr i0 = idx0(idx);
175 uptr i1 = idx1(idx);
176 uptr i2 = idx2(idx);
177 // Printf("%s: %zd => %zd %zd %zd\n", __func__, idx, i0, i1, i2);
178 return l1_[i0].getBit(i1) && l2_[i0][i1].getBit(i2);
179 }
180
181 uptr getAndClearFirstOne() {
182 for (uptr i0 = 0; i0 < kLevel1Size; i0++) {
183 if (l1_[i0].empty()) continue;
184 uptr i1 = l1_[i0].getAndClearFirstOne();
185 uptr i2 = l2_[i0][i1].getAndClearFirstOne();
186 if (!l2_[i0][i1].empty())
187 l1_[i0].setBit(i1);
188 uptr res = i0 * BV::kSize * BV::kSize + i1 * BV::kSize + i2;
189 // Printf("getAndClearFirstOne: %zd %zd %zd => %zd\n", i0, i1, i2, res);
190 return res;
191 }
192 CHECK(0);
193 return 0;
194 }
195
196 // Do "this |= v" and return whether new bits have been added.
197 bool setUnion(const TwoLevelBitVector &v) {
198 bool res = false;
199 for (uptr i0 = 0; i0 < kLevel1Size; i0++) {
200 BV t = v.l1_[i0];
201 while (!t.empty()) {
202 uptr i1 = t.getAndClearFirstOne();
203 if (l1_[i0].setBit(i1))
204 l2_[i0][i1].clear();
205 if (l2_[i0][i1].setUnion(v.l2_[i0][i1]))
206 res = true;
207 }
208 }
209 return res;
210 }
211
212 // Do "this &= v" and return whether any bits have been removed.
213 bool setIntersection(const TwoLevelBitVector &v) {
214 bool res = false;
215 for (uptr i0 = 0; i0 < kLevel1Size; i0++) {
216 if (l1_[i0].setIntersection(v.l1_[i0]))
217 res = true;
218 if (!l1_[i0].empty()) {
219 BV t = l1_[i0];
220 while (!t.empty()) {
221 uptr i1 = t.getAndClearFirstOne();
222 if (l2_[i0][i1].setIntersection(v.l2_[i0][i1]))
223 res = true;
224 if (l2_[i0][i1].empty())
225 l1_[i0].clearBit(i1);
226 }
227 }
228 }
229 return res;
230 }
231
232 // Do "this &= ~v" and return whether any bits have been removed.
233 bool setDifference(const TwoLevelBitVector &v) {
234 bool res = false;
235 for (uptr i0 = 0; i0 < kLevel1Size; i0++) {
236 BV t = l1_[i0];
237 t.setIntersection(v.l1_[i0]);
238 while (!t.empty()) {
239 uptr i1 = t.getAndClearFirstOne();
240 if (l2_[i0][i1].setDifference(v.l2_[i0][i1]))
241 res = true;
242 if (l2_[i0][i1].empty())
243 l1_[i0].clearBit(i1);
244 }
245 }
246 return res;
247 }
248
249 void copyFrom(const TwoLevelBitVector &v) {
250 clear();
251 setUnion(v);
252 }
253
254 // Returns true if 'this' intersects with 'v'.
255 bool intersectsWith(const TwoLevelBitVector &v) const {
256 for (uptr i0 = 0; i0 < kLevel1Size; i0++) {
257 BV t = l1_[i0];
258 t.setIntersection(v.l1_[i0]);
259 while (!t.empty()) {
260 uptr i1 = t.getAndClearFirstOne();
261 if (!v.l1_[i0].getBit(i1)) continue;
262 if (l2_[i0][i1].intersectsWith(v.l2_[i0][i1]))
263 return true;
264 }
265 }
266 return false;
267 }
268
269 // for (TwoLevelBitVector<>::Iterator it(bv); it.hasNext();) {
270 // uptr idx = it.next();
271 // use(idx);
272 // }
273 class Iterator {
274 public:
275 Iterator() { }
276 explicit Iterator(const TwoLevelBitVector &bv) : bv_(bv), i0_(0), i1_(0) {
277 it1_.clear();
278 it2_.clear();
279 }
280
281 bool hasNext() const {
282 if (it1_.hasNext()) return true;
283 for (uptr i = i0_; i < kLevel1Size; i++)
284 if (!bv_.l1_[i].empty()) return true;
285 return false;
286 }
287
288 uptr next() {
289 // Printf("++++: %zd %zd; %d %d; size %zd\n", i0_, i1_, it1_.hasNext(),
290 // it2_.hasNext(), kSize);
291 if (!it1_.hasNext() && !it2_.hasNext()) {
292 for (; i0_ < kLevel1Size; i0_++) {
293 if (bv_.l1_[i0_].empty()) continue;
294 it1_ = typename BV::Iterator(bv_.l1_[i0_]);
295 // Printf("+i0: %zd %zd; %d %d; size %zd\n", i0_, i1_, it1_.hasNext(),
296 // it2_.hasNext(), kSize);
297 break;
298 }
299 }
300 if (!it2_.hasNext()) {
301 CHECK(it1_.hasNext());
302 i1_ = it1_.next();
303 it2_ = typename BV::Iterator(bv_.l2_[i0_][i1_]);
304 // Printf("++i1: %zd %zd; %d %d; size %zd\n", i0_, i1_, it1_.hasNext(),
305 // it2_.hasNext(), kSize);
306 }
307 CHECK(it2_.hasNext());
308 uptr i2 = it2_.next();
309 uptr res = i0_ * BV::kSize * BV::kSize + i1_ * BV::kSize + i2;
310 // Printf("+ret: %zd %zd; %d %d; size %zd; res: %zd\n", i0_, i1_,
311 // it1_.hasNext(), it2_.hasNext(), kSize, res);
312 if (!it1_.hasNext() && !it2_.hasNext())
313 i0_++;
314 return res;
315 }
316
317 private:
318 const TwoLevelBitVector &bv_;
319 uptr i0_, i1_;
320 typename BV::Iterator it1_, it2_;
321 };
322
323 private:
324 void check(uptr idx) const { CHECK_LE(idx, size()); }
325
326 uptr idx0(uptr idx) const {
327 uptr res = idx / (BV::kSize * BV::kSize);
328 CHECK_LE(res, kLevel1Size);
329 return res;
330 }
331
332 uptr idx1(uptr idx) const {
333 uptr res = (idx / BV::kSize) % BV::kSize;
334 CHECK_LE(res, BV::kSize);
335 return res;
336 }
337
338 uptr idx2(uptr idx) const {
339 uptr res = idx % BV::kSize;
340 CHECK_LE(res, BV::kSize);
341 return res;
342 }
343
344 BV l1_[kLevel1Size];
345 BV l2_[kLevel1Size][BV::kSize];
346};
347
348} // namespace __sanitizer
349
350#endif // SANITIZER_BITVECTOR_H
lib/tsan/sanitizer_common/sanitizer_bvgraph.h created+164
...@@ -0,0 +1,164 @@
1//===-- sanitizer_bvgraph.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.
10// BVGraph -- a directed graph.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef SANITIZER_BVGRAPH_H
15#define SANITIZER_BVGRAPH_H
16
17#include "sanitizer_common.h"
18#include "sanitizer_bitvector.h"
19
20namespace __sanitizer {
21
22// Directed graph of fixed size implemented as an array of bit vectors.
23// Not thread-safe, all accesses should be protected by an external lock.
24template<class BV>
25class BVGraph {
26 public:
27 enum SizeEnum : uptr { kSize = BV::kSize };
28 uptr size() const { return kSize; }
29 // No CTOR.
30 void clear() {
31 for (uptr i = 0; i < size(); i++)
32 v[i].clear();
33 }
34
35 bool empty() const {
36 for (uptr i = 0; i < size(); i++)
37 if (!v[i].empty())
38 return false;
39 return true;
40 }
41
42 // Returns true if a new edge was added.
43 bool addEdge(uptr from, uptr to) {
44 check(from, to);
45 return v[from].setBit(to);
46 }
47
48 // Returns true if at least one new edge was added.
49 uptr addEdges(const BV &from, uptr to, uptr added_edges[],
50 uptr max_added_edges) {
51 uptr res = 0;
52 t1.copyFrom(from);
53 while (!t1.empty()) {
54 uptr node = t1.getAndClearFirstOne();
55 if (v[node].setBit(to))
56 if (res < max_added_edges)
57 added_edges[res++] = node;
58 }
59 return res;
60 }
61
62 // *EXPERIMENTAL*
63 // Returns true if an edge from=>to exist.
64 // This function does not use any global state except for 'this' itself,
65 // and thus can be called from different threads w/o locking.
66 // This would be racy.
67 // FIXME: investigate how much we can prove about this race being "benign".
68 bool hasEdge(uptr from, uptr to) { return v[from].getBit(to); }
69
70 // Returns true if the edge from=>to was removed.
71 bool removeEdge(uptr from, uptr to) {
72 return v[from].clearBit(to);
73 }
74
75 // Returns true if at least one edge *=>to was removed.
76 bool removeEdgesTo(const BV &to) {
77 bool res = 0;
78 for (uptr from = 0; from < size(); from++) {
79 if (v[from].setDifference(to))
80 res = true;
81 }
82 return res;
83 }
84
85 // Returns true if at least one edge from=>* was removed.
86 bool removeEdgesFrom(const BV &from) {
87 bool res = false;
88 t1.copyFrom(from);
89 while (!t1.empty()) {
90 uptr idx = t1.getAndClearFirstOne();
91 if (!v[idx].empty()) {
92 v[idx].clear();
93 res = true;
94 }
95 }
96 return res;
97 }
98
99 void removeEdgesFrom(uptr from) {
100 return v[from].clear();
101 }
102
103 bool hasEdge(uptr from, uptr to) const {
104 check(from, to);
105 return v[from].getBit(to);
106 }
107
108 // Returns true if there is a path from the node 'from'
109 // to any of the nodes in 'targets'.
110 bool isReachable(uptr from, const BV &targets) {
111 BV &to_visit = t1,
112 &visited = t2;
113 to_visit.copyFrom(v[from]);
114 visited.clear();
115 visited.setBit(from);
116 while (!to_visit.empty()) {
117 uptr idx = to_visit.getAndClearFirstOne();
118 if (visited.setBit(idx))
119 to_visit.setUnion(v[idx]);
120 }
121 return targets.intersectsWith(visited);
122 }
123
124 // Finds a path from 'from' to one of the nodes in 'target',
125 // stores up to 'path_size' items of the path into 'path',
126 // returns the path length, or 0 if there is no path of size 'path_size'.
127 uptr findPath(uptr from, const BV &targets, uptr *path, uptr path_size) {
128 if (path_size == 0)
129 return 0;
130 path[0] = from;
131 if (targets.getBit(from))
132 return 1;
133 // The function is recursive, so we don't want to create BV on stack.
134 // Instead of a getAndClearFirstOne loop we use the slower iterator.
135 for (typename BV::Iterator it(v[from]); it.hasNext(); ) {
136 uptr idx = it.next();
137 if (uptr res = findPath(idx, targets, path + 1, path_size - 1))
138 return res + 1;
139 }
140 return 0;
141 }
142
143 // Same as findPath, but finds a shortest path.
144 uptr findShortestPath(uptr from, const BV &targets, uptr *path,
145 uptr path_size) {
146 for (uptr p = 1; p <= path_size; p++)
147 if (findPath(from, targets, path, p) == p)
148 return p;
149 return 0;
150 }
151
152 private:
153 void check(uptr idx1, uptr idx2) const {
154 CHECK_LT(idx1, size());
155 CHECK_LT(idx2, size());
156 }
157 BV v[kSize];
158 // Keep temporary vectors here since we can not create large objects on stack.
159 BV t1, t2;
160};
161
162} // namespace __sanitizer
163
164#endif // SANITIZER_BVGRAPH_H
lib/tsan/sanitizer_common/sanitizer_common.cpp created+348
...@@ -0,0 +1,348 @@
1//===-- sanitizer_common.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 shared between AddressSanitizer and ThreadSanitizer
10// run-time libraries.
11//===----------------------------------------------------------------------===//
12
13#include "sanitizer_common.h"
14#include "sanitizer_allocator_interface.h"
15#include "sanitizer_allocator_internal.h"
16#include "sanitizer_atomic.h"
17#include "sanitizer_flags.h"
18#include "sanitizer_libc.h"
19#include "sanitizer_placement_new.h"
20
21namespace __sanitizer {
22
23const char *SanitizerToolName = "SanitizerTool";
24
25atomic_uint32_t current_verbosity;
26uptr PageSizeCached;
27u32 NumberOfCPUsCached;
28
29// PID of the tracer task in StopTheWorld. It shares the address space with the
30// main process, but has a different PID and thus requires special handling.
31uptr stoptheworld_tracer_pid = 0;
32// Cached pid of parent process - if the parent process dies, we want to keep
33// writing to the same log file.
34uptr stoptheworld_tracer_ppid = 0;
35
36void NORETURN ReportMmapFailureAndDie(uptr size, const char *mem_type,
37 const char *mmap_type, error_t err,
38 bool raw_report) {
39 static int recursion_count;
40 if (SANITIZER_RTEMS || raw_report || recursion_count) {
41 // If we are on RTEMS or raw report is requested or we went into recursion,
42 // just die. The Report() and CHECK calls below may call mmap recursively
43 // and fail.
44 RawWrite("ERROR: Failed to mmap\n");
45 Die();
46 }
47 recursion_count++;
48 Report("ERROR: %s failed to "
49 "%s 0x%zx (%zd) bytes of %s (error code: %d)\n",
50 SanitizerToolName, mmap_type, size, size, mem_type, err);
51#if !SANITIZER_GO
52 DumpProcessMap();
53#endif
54 UNREACHABLE("unable to mmap");
55}
56
57typedef bool UptrComparisonFunction(const uptr &a, const uptr &b);
58typedef bool U32ComparisonFunction(const u32 &a, const u32 &b);
59
60const char *StripPathPrefix(const char *filepath,
61 const char *strip_path_prefix) {
62 if (!filepath) return nullptr;
63 if (!strip_path_prefix) return filepath;
64 const char *res = filepath;
65 if (const char *pos = internal_strstr(filepath, strip_path_prefix))
66 res = pos + internal_strlen(strip_path_prefix);
67 if (res[0] == '.' && res[1] == '/')
68 res += 2;
69 return res;
70}
71
72const char *StripModuleName(const char *module) {
73 if (!module)
74 return nullptr;
75 if (SANITIZER_WINDOWS) {
76 // On Windows, both slash and backslash are possible.
77 // Pick the one that goes last.
78 if (const char *bslash_pos = internal_strrchr(module, '\\'))
79 return StripModuleName(bslash_pos + 1);
80 }
81 if (const char *slash_pos = internal_strrchr(module, '/')) {
82 return slash_pos + 1;
83 }
84 return module;
85}
86
87void ReportErrorSummary(const char *error_message, const char *alt_tool_name) {
88 if (!common_flags()->print_summary)
89 return;
90 InternalScopedString buff(kMaxSummaryLength);
91 buff.append("SUMMARY: %s: %s",
92 alt_tool_name ? alt_tool_name : SanitizerToolName, error_message);
93 __sanitizer_report_error_summary(buff.data());
94}
95
96// Removes the ANSI escape sequences from the input string (in-place).
97void RemoveANSIEscapeSequencesFromString(char *str) {
98 if (!str)
99 return;
100
101 // We are going to remove the escape sequences in place.
102 char *s = str;
103 char *z = str;
104 while (*s != '\0') {
105 CHECK_GE(s, z);
106 // Skip over ANSI escape sequences with pointer 's'.
107 if (*s == '\033' && *(s + 1) == '[') {
108 s = internal_strchrnul(s, 'm');
109 if (*s == '\0') {
110 break;
111 }
112 s++;
113 continue;
114 }
115 // 's' now points at a character we want to keep. Copy over the buffer
116 // content if the escape sequence has been perviously skipped andadvance
117 // both pointers.
118 if (s != z)
119 *z = *s;
120
121 // If we have not seen an escape sequence, just advance both pointers.
122 z++;
123 s++;
124 }
125
126 // Null terminate the string.
127 *z = '\0';
128}
129
130void LoadedModule::set(const char *module_name, uptr base_address) {
131 clear();
132 full_name_ = internal_strdup(module_name);
133 base_address_ = base_address;
134}
135
136void LoadedModule::set(const char *module_name, uptr base_address,
137 ModuleArch arch, u8 uuid[kModuleUUIDSize],
138 bool instrumented) {
139 set(module_name, base_address);
140 arch_ = arch;
141 internal_memcpy(uuid_, uuid, sizeof(uuid_));
142 instrumented_ = instrumented;
143}
144
145void LoadedModule::clear() {
146 InternalFree(full_name_);
147 base_address_ = 0;
148 max_executable_address_ = 0;
149 full_name_ = nullptr;
150 arch_ = kModuleArchUnknown;
151 internal_memset(uuid_, 0, kModuleUUIDSize);
152 instrumented_ = false;
153 while (!ranges_.empty()) {
154 AddressRange *r = ranges_.front();
155 ranges_.pop_front();
156 InternalFree(r);
157 }
158}
159
160void LoadedModule::addAddressRange(uptr beg, uptr end, bool executable,
161 bool writable, const char *name) {
162 void *mem = InternalAlloc(sizeof(AddressRange));
163 AddressRange *r =
164 new(mem) AddressRange(beg, end, executable, writable, name);
165 ranges_.push_back(r);
166 if (executable && end > max_executable_address_)
167 max_executable_address_ = end;
168}
169
170bool LoadedModule::containsAddress(uptr address) const {
171 for (const AddressRange &r : ranges()) {
172 if (r.beg <= address && address < r.end)
173 return true;
174 }
175 return false;
176}
177
178static atomic_uintptr_t g_total_mmaped;
179
180void IncreaseTotalMmap(uptr size) {
181 if (!common_flags()->mmap_limit_mb) return;
182 uptr total_mmaped =
183 atomic_fetch_add(&g_total_mmaped, size, memory_order_relaxed) + size;
184 // Since for now mmap_limit_mb is not a user-facing flag, just kill
185 // a program. Use RAW_CHECK to avoid extra mmaps in reporting.
186 RAW_CHECK((total_mmaped >> 20) < common_flags()->mmap_limit_mb);
187}
188
189void DecreaseTotalMmap(uptr size) {
190 if (!common_flags()->mmap_limit_mb) return;
191 atomic_fetch_sub(&g_total_mmaped, size, memory_order_relaxed);
192}
193
194bool TemplateMatch(const char *templ, const char *str) {
195 if ((!str) || str[0] == 0)
196 return false;
197 bool start = false;
198 if (templ && templ[0] == '^') {
199 start = true;
200 templ++;
201 }
202 bool asterisk = false;
203 while (templ && templ[0]) {
204 if (templ[0] == '*') {
205 templ++;
206 start = false;
207 asterisk = true;
208 continue;
209 }
210 if (templ[0] == '$')
211 return str[0] == 0 || asterisk;
212 if (str[0] == 0)
213 return false;
214 char *tpos = (char*)internal_strchr(templ, '*');
215 char *tpos1 = (char*)internal_strchr(templ, '$');
216 if ((!tpos) || (tpos1 && tpos1 < tpos))
217 tpos = tpos1;
218 if (tpos)
219 tpos[0] = 0;
220 const char *str0 = str;
221 const char *spos = internal_strstr(str, templ);
222 str = spos + internal_strlen(templ);
223 templ = tpos;
224 if (tpos)
225 tpos[0] = tpos == tpos1 ? '$' : '*';
226 if (!spos)
227 return false;
228 if (start && spos != str0)
229 return false;
230 start = false;
231 asterisk = false;
232 }
233 return true;
234}
235
236static char binary_name_cache_str[kMaxPathLength];
237static char process_name_cache_str[kMaxPathLength];
238
239const char *GetProcessName() {
240 return process_name_cache_str;
241}
242
243static uptr ReadProcessName(/*out*/ char *buf, uptr buf_len) {
244 ReadLongProcessName(buf, buf_len);
245 char *s = const_cast<char *>(StripModuleName(buf));
246 uptr len = internal_strlen(s);
247 if (s != buf) {
248 internal_memmove(buf, s, len);
249 buf[len] = '\0';
250 }
251 return len;
252}
253
254void UpdateProcessName() {
255 ReadProcessName(process_name_cache_str, sizeof(process_name_cache_str));
256}
257
258// Call once to make sure that binary_name_cache_str is initialized
259void CacheBinaryName() {
260 if (binary_name_cache_str[0] != '\0')
261 return;
262 ReadBinaryName(binary_name_cache_str, sizeof(binary_name_cache_str));
263 ReadProcessName(process_name_cache_str, sizeof(process_name_cache_str));
264}
265
266uptr ReadBinaryNameCached(/*out*/char *buf, uptr buf_len) {
267 CacheBinaryName();
268 uptr name_len = internal_strlen(binary_name_cache_str);
269 name_len = (name_len < buf_len - 1) ? name_len : buf_len - 1;
270 if (buf_len == 0)
271 return 0;
272 internal_memcpy(buf, binary_name_cache_str, name_len);
273 buf[name_len] = '\0';
274 return name_len;
275}
276
277#if !SANITIZER_GO
278void PrintCmdline() {
279 char **argv = GetArgv();
280 if (!argv) return;
281 Printf("\nCommand: ");
282 for (uptr i = 0; argv[i]; ++i)
283 Printf("%s ", argv[i]);
284 Printf("\n\n");
285}
286#endif
287
288// Malloc hooks.
289static const int kMaxMallocFreeHooks = 5;
290struct MallocFreeHook {
291 void (*malloc_hook)(const void *, uptr);
292 void (*free_hook)(const void *);
293};
294
295static MallocFreeHook MFHooks[kMaxMallocFreeHooks];
296
297void RunMallocHooks(const void *ptr, uptr size) {
298 for (int i = 0; i < kMaxMallocFreeHooks; i++) {
299 auto hook = MFHooks[i].malloc_hook;
300 if (!hook) return;
301 hook(ptr, size);
302 }
303}
304
305void RunFreeHooks(const void *ptr) {
306 for (int i = 0; i < kMaxMallocFreeHooks; i++) {
307 auto hook = MFHooks[i].free_hook;
308 if (!hook) return;
309 hook(ptr);
310 }
311}
312
313static int InstallMallocFreeHooks(void (*malloc_hook)(const void *, uptr),
314 void (*free_hook)(const void *)) {
315 if (!malloc_hook || !free_hook) return 0;
316 for (int i = 0; i < kMaxMallocFreeHooks; i++) {
317 if (MFHooks[i].malloc_hook == nullptr) {
318 MFHooks[i].malloc_hook = malloc_hook;
319 MFHooks[i].free_hook = free_hook;
320 return i + 1;
321 }
322 }
323 return 0;
324}
325
326} // namespace __sanitizer
327
328using namespace __sanitizer;
329
330extern "C" {
331SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_report_error_summary,
332 const char *error_summary) {
333 Printf("%s\n", error_summary);
334}
335
336SANITIZER_INTERFACE_ATTRIBUTE
337int __sanitizer_acquire_crash_state() {
338 static atomic_uint8_t in_crash_state = {};
339 return !atomic_exchange(&in_crash_state, 1, memory_order_relaxed);
340}
341
342SANITIZER_INTERFACE_ATTRIBUTE
343int __sanitizer_install_malloc_and_free_hooks(void (*malloc_hook)(const void *,
344 uptr),
345 void (*free_hook)(const void *)) {
346 return InstallMallocFreeHooks(malloc_hook, free_hook);
347}
348} // extern "C"
lib/tsan/sanitizer_common/sanitizer_common.h created+1002
...@@ -0,0 +1,1002 @@
1//===-- sanitizer_common.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 run-time libraries of sanitizers.
10//
11// It declares common functions and classes that are used in both runtimes.
12// Implementation of some functions are provided in sanitizer_common, while
13// others must be defined by run-time library itself.
14//===----------------------------------------------------------------------===//
15#ifndef SANITIZER_COMMON_H
16#define SANITIZER_COMMON_H
17
18#include "sanitizer_flags.h"
19#include "sanitizer_interface_internal.h"
20#include "sanitizer_internal_defs.h"
21#include "sanitizer_libc.h"
22#include "sanitizer_list.h"
23#include "sanitizer_mutex.h"
24
25#if defined(_MSC_VER) && !defined(__clang__)
26extern "C" void _ReadWriteBarrier();
27#pragma intrinsic(_ReadWriteBarrier)
28#endif
29
30namespace __sanitizer {
31
32struct AddressInfo;
33struct BufferedStackTrace;
34struct SignalContext;
35struct StackTrace;
36
37// Constants.
38const uptr kWordSize = SANITIZER_WORDSIZE / 8;
39const uptr kWordSizeInBits = 8 * kWordSize;
40
41const uptr kCacheLineSize = SANITIZER_CACHE_LINE_SIZE;
42
43const uptr kMaxPathLength = 4096;
44
45const uptr kMaxThreadStackSize = 1 << 30; // 1Gb
46
47static const uptr kErrorMessageBufferSize = 1 << 16;
48
49// Denotes fake PC values that come from JIT/JAVA/etc.
50// For such PC values __tsan_symbolize_external_ex() will be called.
51const u64 kExternalPCBit = 1ULL << 60;
52
53extern const char *SanitizerToolName; // Can be changed by the tool.
54
55extern atomic_uint32_t current_verbosity;
56INLINE void SetVerbosity(int verbosity) {
57 atomic_store(&current_verbosity, verbosity, memory_order_relaxed);
58}
59INLINE int Verbosity() {
60 return atomic_load(&current_verbosity, memory_order_relaxed);
61}
62
63#if SANITIZER_ANDROID
64INLINE uptr GetPageSize() {
65// Android post-M sysconf(_SC_PAGESIZE) crashes if called from .preinit_array.
66 return 4096;
67}
68INLINE uptr GetPageSizeCached() {
69 return 4096;
70}
71#else
72uptr GetPageSize();
73extern uptr PageSizeCached;
74INLINE uptr GetPageSizeCached() {
75 if (!PageSizeCached)
76 PageSizeCached = GetPageSize();
77 return PageSizeCached;
78}
79#endif
80uptr GetMmapGranularity();
81uptr GetMaxVirtualAddress();
82uptr GetMaxUserVirtualAddress();
83// Threads
84tid_t GetTid();
85int TgKill(pid_t pid, tid_t tid, int sig);
86uptr GetThreadSelf();
87void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
88 uptr *stack_bottom);
89void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
90 uptr *tls_addr, uptr *tls_size);
91
92// Memory management
93void *MmapOrDie(uptr size, const char *mem_type, bool raw_report = false);
94INLINE void *MmapOrDieQuietly(uptr size, const char *mem_type) {
95 return MmapOrDie(size, mem_type, /*raw_report*/ true);
96}
97void UnmapOrDie(void *addr, uptr size);
98// Behaves just like MmapOrDie, but tolerates out of memory condition, in that
99// case returns nullptr.
100void *MmapOrDieOnFatalError(uptr size, const char *mem_type);
101bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name = nullptr)
102 WARN_UNUSED_RESULT;
103bool MmapFixedSuperNoReserve(uptr fixed_addr, uptr size,
104 const char *name = nullptr) WARN_UNUSED_RESULT;
105void *MmapNoReserveOrDie(uptr size, const char *mem_type);
106void *MmapFixedOrDie(uptr fixed_addr, uptr size, const char *name = nullptr);
107// Behaves just like MmapFixedOrDie, but tolerates out of memory condition, in
108// that case returns nullptr.
109void *MmapFixedOrDieOnFatalError(uptr fixed_addr, uptr size,
110 const char *name = nullptr);
111void *MmapFixedNoAccess(uptr fixed_addr, uptr size, const char *name = nullptr);
112void *MmapNoAccess(uptr size);
113// Map aligned chunk of address space; size and alignment are powers of two.
114// Dies on all but out of memory errors, in the latter case returns nullptr.
115void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment,
116 const char *mem_type);
117// Disallow access to a memory range. Use MmapFixedNoAccess to allocate an
118// unaccessible memory.
119bool MprotectNoAccess(uptr addr, uptr size);
120bool MprotectReadOnly(uptr addr, uptr size);
121
122void MprotectMallocZones(void *addr, int prot);
123
124// Find an available address space.
125uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,
126 uptr *largest_gap_found, uptr *max_occupied_addr);
127
128// Used to check if we can map shadow memory to a fixed location.
129bool MemoryRangeIsAvailable(uptr range_start, uptr range_end);
130// Releases memory pages entirely within the [beg, end] address range. Noop if
131// the provided range does not contain at least one entire page.
132void ReleaseMemoryPagesToOS(uptr beg, uptr end);
133void IncreaseTotalMmap(uptr size);
134void DecreaseTotalMmap(uptr size);
135uptr GetRSS();
136void SetShadowRegionHugePageMode(uptr addr, uptr length);
137bool DontDumpShadowMemory(uptr addr, uptr length);
138// Check if the built VMA size matches the runtime one.
139void CheckVMASize();
140void RunMallocHooks(const void *ptr, uptr size);
141void RunFreeHooks(const void *ptr);
142
143class ReservedAddressRange {
144 public:
145 uptr Init(uptr size, const char *name = nullptr, uptr fixed_addr = 0);
146 uptr InitAligned(uptr size, uptr align, const char *name = nullptr);
147 uptr Map(uptr fixed_addr, uptr size, const char *name = nullptr);
148 uptr MapOrDie(uptr fixed_addr, uptr size, const char *name = nullptr);
149 void Unmap(uptr addr, uptr size);
150 void *base() const { return base_; }
151 uptr size() const { return size_; }
152
153 private:
154 void* base_;
155 uptr size_;
156 const char* name_;
157 uptr os_handle_;
158};
159
160typedef void (*fill_profile_f)(uptr start, uptr rss, bool file,
161 /*out*/uptr *stats, uptr stats_size);
162
163// Parse the contents of /proc/self/smaps and generate a memory profile.
164// |cb| is a tool-specific callback that fills the |stats| array containing
165// |stats_size| elements.
166void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size);
167
168// Simple low-level (mmap-based) allocator for internal use. Doesn't have
169// constructor, so all instances of LowLevelAllocator should be
170// linker initialized.
171class LowLevelAllocator {
172 public:
173 // Requires an external lock.
174 void *Allocate(uptr size);
175 private:
176 char *allocated_end_;
177 char *allocated_current_;
178};
179// Set the min alignment of LowLevelAllocator to at least alignment.
180void SetLowLevelAllocateMinAlignment(uptr alignment);
181typedef void (*LowLevelAllocateCallback)(uptr ptr, uptr size);
182// Allows to register tool-specific callbacks for LowLevelAllocator.
183// Passing NULL removes the callback.
184void SetLowLevelAllocateCallback(LowLevelAllocateCallback callback);
185
186// IO
187void CatastrophicErrorWrite(const char *buffer, uptr length);
188void RawWrite(const char *buffer);
189bool ColorizeReports();
190void RemoveANSIEscapeSequencesFromString(char *buffer);
191void Printf(const char *format, ...);
192void Report(const char *format, ...);
193void SetPrintfAndReportCallback(void (*callback)(const char *));
194#define VReport(level, ...) \
195 do { \
196 if ((uptr)Verbosity() >= (level)) Report(__VA_ARGS__); \
197 } while (0)
198#define VPrintf(level, ...) \
199 do { \
200 if ((uptr)Verbosity() >= (level)) Printf(__VA_ARGS__); \
201 } while (0)
202
203// Lock sanitizer error reporting and protects against nested errors.
204class ScopedErrorReportLock {
205 public:
206 ScopedErrorReportLock();
207 ~ScopedErrorReportLock();
208
209 static void CheckLocked();
210};
211
212extern uptr stoptheworld_tracer_pid;
213extern uptr stoptheworld_tracer_ppid;
214
215bool IsAccessibleMemoryRange(uptr beg, uptr size);
216
217// Error report formatting.
218const char *StripPathPrefix(const char *filepath,
219 const char *strip_file_prefix);
220// Strip the directories from the module name.
221const char *StripModuleName(const char *module);
222
223// OS
224uptr ReadBinaryName(/*out*/char *buf, uptr buf_len);
225uptr ReadBinaryNameCached(/*out*/char *buf, uptr buf_len);
226uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len);
227const char *GetProcessName();
228void UpdateProcessName();
229void CacheBinaryName();
230void DisableCoreDumperIfNecessary();
231void DumpProcessMap();
232void PrintModuleMap();
233const char *GetEnv(const char *name);
234bool SetEnv(const char *name, const char *value);
235
236u32 GetUid();
237void ReExec();
238void CheckASLR();
239void CheckMPROTECT();
240char **GetArgv();
241char **GetEnviron();
242void PrintCmdline();
243bool StackSizeIsUnlimited();
244void SetStackSizeLimitInBytes(uptr limit);
245bool AddressSpaceIsUnlimited();
246void SetAddressSpaceUnlimited();
247void AdjustStackSize(void *attr);
248void PlatformPrepareForSandboxing(__sanitizer_sandbox_arguments *args);
249void SetSandboxingCallback(void (*f)());
250
251void InitializeCoverage(bool enabled, const char *coverage_dir);
252
253void InitTlsSize();
254uptr GetTlsSize();
255
256// Other
257void SleepForSeconds(int seconds);
258void SleepForMillis(int millis);
259u64 NanoTime();
260u64 MonotonicNanoTime();
261int Atexit(void (*function)(void));
262bool TemplateMatch(const char *templ, const char *str);
263
264// Exit
265void NORETURN Abort();
266void NORETURN Die();
267void NORETURN
268CheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2);
269void NORETURN ReportMmapFailureAndDie(uptr size, const char *mem_type,
270 const char *mmap_type, error_t err,
271 bool raw_report = false);
272
273// Specific tools may override behavior of "Die" and "CheckFailed" functions
274// to do tool-specific job.
275typedef void (*DieCallbackType)(void);
276
277// It's possible to add several callbacks that would be run when "Die" is
278// called. The callbacks will be run in the opposite order. The tools are
279// strongly recommended to setup all callbacks during initialization, when there
280// is only a single thread.
281bool AddDieCallback(DieCallbackType callback);
282bool RemoveDieCallback(DieCallbackType callback);
283
284void SetUserDieCallback(DieCallbackType callback);
285
286typedef void (*CheckFailedCallbackType)(const char *, int, const char *,
287 u64, u64);
288void SetCheckFailedCallback(CheckFailedCallbackType callback);
289
290// Callback will be called if soft_rss_limit_mb is given and the limit is
291// exceeded (exceeded==true) or if rss went down below the limit
292// (exceeded==false).
293// The callback should be registered once at the tool init time.
294void SetSoftRssLimitExceededCallback(void (*Callback)(bool exceeded));
295
296// Functions related to signal handling.
297typedef void (*SignalHandlerType)(int, void *, void *);
298HandleSignalMode GetHandleSignalMode(int signum);
299void InstallDeadlySignalHandlers(SignalHandlerType handler);
300
301// Signal reporting.
302// Each sanitizer uses slightly different implementation of stack unwinding.
303typedef void (*UnwindSignalStackCallbackType)(const SignalContext &sig,
304 const void *callback_context,
305 BufferedStackTrace *stack);
306// Print deadly signal report and die.
307void HandleDeadlySignal(void *siginfo, void *context, u32 tid,
308 UnwindSignalStackCallbackType unwind,
309 const void *unwind_context);
310
311// Part of HandleDeadlySignal, exposed for asan.
312void StartReportDeadlySignal();
313// Part of HandleDeadlySignal, exposed for asan.
314void ReportDeadlySignal(const SignalContext &sig, u32 tid,
315 UnwindSignalStackCallbackType unwind,
316 const void *unwind_context);
317
318// Alternative signal stack (POSIX-only).
319void SetAlternateSignalStack();
320void UnsetAlternateSignalStack();
321
322// We don't want a summary too long.
323const int kMaxSummaryLength = 1024;
324// Construct a one-line string:
325// SUMMARY: SanitizerToolName: error_message
326// and pass it to __sanitizer_report_error_summary.
327// If alt_tool_name is provided, it's used in place of SanitizerToolName.
328void ReportErrorSummary(const char *error_message,
329 const char *alt_tool_name = nullptr);
330// Same as above, but construct error_message as:
331// error_type file:line[:column][ function]
332void ReportErrorSummary(const char *error_type, const AddressInfo &info,
333 const char *alt_tool_name = nullptr);
334// Same as above, but obtains AddressInfo by symbolizing top stack trace frame.
335void ReportErrorSummary(const char *error_type, const StackTrace *trace,
336 const char *alt_tool_name = nullptr);
337
338void ReportMmapWriteExec(int prot);
339
340// Math
341#if SANITIZER_WINDOWS && !defined(__clang__) && !defined(__GNUC__)
342extern "C" {
343unsigned char _BitScanForward(unsigned long *index, unsigned long mask);
344unsigned char _BitScanReverse(unsigned long *index, unsigned long mask);
345#if defined(_WIN64)
346unsigned char _BitScanForward64(unsigned long *index, unsigned __int64 mask);
347unsigned char _BitScanReverse64(unsigned long *index, unsigned __int64 mask);
348#endif
349}
350#endif
351
352INLINE uptr MostSignificantSetBitIndex(uptr x) {
353 CHECK_NE(x, 0U);
354 unsigned long up;
355#if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__)
356# ifdef _WIN64
357 up = SANITIZER_WORDSIZE - 1 - __builtin_clzll(x);
358# else
359 up = SANITIZER_WORDSIZE - 1 - __builtin_clzl(x);
360# endif
361#elif defined(_WIN64)
362 _BitScanReverse64(&up, x);
363#else
364 _BitScanReverse(&up, x);
365#endif
366 return up;
367}
368
369INLINE uptr LeastSignificantSetBitIndex(uptr x) {
370 CHECK_NE(x, 0U);
371 unsigned long up;
372#if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__)
373# ifdef _WIN64
374 up = __builtin_ctzll(x);
375# else
376 up = __builtin_ctzl(x);
377# endif
378#elif defined(_WIN64)
379 _BitScanForward64(&up, x);
380#else
381 _BitScanForward(&up, x);
382#endif
383 return up;
384}
385
386INLINE bool IsPowerOfTwo(uptr x) {
387 return (x & (x - 1)) == 0;
388}
389
390INLINE uptr RoundUpToPowerOfTwo(uptr size) {
391 CHECK(size);
392 if (IsPowerOfTwo(size)) return size;
393
394 uptr up = MostSignificantSetBitIndex(size);
395 CHECK_LT(size, (1ULL << (up + 1)));
396 CHECK_GT(size, (1ULL << up));
397 return 1ULL << (up + 1);
398}
399
400INLINE uptr RoundUpTo(uptr size, uptr boundary) {
401 RAW_CHECK(IsPowerOfTwo(boundary));
402 return (size + boundary - 1) & ~(boundary - 1);
403}
404
405INLINE uptr RoundDownTo(uptr x, uptr boundary) {
406 return x & ~(boundary - 1);
407}
408
409INLINE bool IsAligned(uptr a, uptr alignment) {
410 return (a & (alignment - 1)) == 0;
411}
412
413INLINE uptr Log2(uptr x) {
414 CHECK(IsPowerOfTwo(x));
415 return LeastSignificantSetBitIndex(x);
416}
417
418// Don't use std::min, std::max or std::swap, to minimize dependency
419// on libstdc++.
420template<class T> T Min(T a, T b) { return a < b ? a : b; }
421template<class T> T Max(T a, T b) { return a > b ? a : b; }
422template<class T> void Swap(T& a, T& b) {
423 T tmp = a;
424 a = b;
425 b = tmp;
426}
427
428// Char handling
429INLINE bool IsSpace(int c) {
430 return (c == ' ') || (c == '\n') || (c == '\t') ||
431 (c == '\f') || (c == '\r') || (c == '\v');
432}
433INLINE bool IsDigit(int c) {
434 return (c >= '0') && (c <= '9');
435}
436INLINE int ToLower(int c) {
437 return (c >= 'A' && c <= 'Z') ? (c + 'a' - 'A') : c;
438}
439
440// A low-level vector based on mmap. May incur a significant memory overhead for
441// small vectors.
442// WARNING: The current implementation supports only POD types.
443template<typename T>
444class InternalMmapVectorNoCtor {
445 public:
446 void Initialize(uptr initial_capacity) {
447 capacity_bytes_ = 0;
448 size_ = 0;
449 data_ = 0;
450 reserve(initial_capacity);
451 }
452 void Destroy() { UnmapOrDie(data_, capacity_bytes_); }
453 T &operator[](uptr i) {
454 CHECK_LT(i, size_);
455 return data_[i];
456 }
457 const T &operator[](uptr i) const {
458 CHECK_LT(i, size_);
459 return data_[i];
460 }
461 void push_back(const T &element) {
462 CHECK_LE(size_, capacity());
463 if (size_ == capacity()) {
464 uptr new_capacity = RoundUpToPowerOfTwo(size_ + 1);
465 Realloc(new_capacity);
466 }
467 internal_memcpy(&data_[size_++], &element, sizeof(T));
468 }
469 T &back() {
470 CHECK_GT(size_, 0);
471 return data_[size_ - 1];
472 }
473 void pop_back() {
474 CHECK_GT(size_, 0);
475 size_--;
476 }
477 uptr size() const {
478 return size_;
479 }
480 const T *data() const {
481 return data_;
482 }
483 T *data() {
484 return data_;
485 }
486 uptr capacity() const { return capacity_bytes_ / sizeof(T); }
487 void reserve(uptr new_size) {
488 // Never downsize internal buffer.
489 if (new_size > capacity())
490 Realloc(new_size);
491 }
492 void resize(uptr new_size) {
493 if (new_size > size_) {
494 reserve(new_size);
495 internal_memset(&data_[size_], 0, sizeof(T) * (new_size - size_));
496 }
497 size_ = new_size;
498 }
499
500 void clear() { size_ = 0; }
501 bool empty() const { return size() == 0; }
502
503 const T *begin() const {
504 return data();
505 }
506 T *begin() {
507 return data();
508 }
509 const T *end() const {
510 return data() + size();
511 }
512 T *end() {
513 return data() + size();
514 }
515
516 void swap(InternalMmapVectorNoCtor &other) {
517 Swap(data_, other.data_);
518 Swap(capacity_bytes_, other.capacity_bytes_);
519 Swap(size_, other.size_);
520 }
521
522 private:
523 void Realloc(uptr new_capacity) {
524 CHECK_GT(new_capacity, 0);
525 CHECK_LE(size_, new_capacity);
526 uptr new_capacity_bytes =
527 RoundUpTo(new_capacity * sizeof(T), GetPageSizeCached());
528 T *new_data = (T *)MmapOrDie(new_capacity_bytes, "InternalMmapVector");
529 internal_memcpy(new_data, data_, size_ * sizeof(T));
530 UnmapOrDie(data_, capacity_bytes_);
531 data_ = new_data;
532 capacity_bytes_ = new_capacity_bytes;
533 }
534
535 T *data_;
536 uptr capacity_bytes_;
537 uptr size_;
538};
539
540template <typename T>
541bool operator==(const InternalMmapVectorNoCtor<T> &lhs,
542 const InternalMmapVectorNoCtor<T> &rhs) {
543 if (lhs.size() != rhs.size()) return false;
544 return internal_memcmp(lhs.data(), rhs.data(), lhs.size() * sizeof(T)) == 0;
545}
546
547template <typename T>
548bool operator!=(const InternalMmapVectorNoCtor<T> &lhs,
549 const InternalMmapVectorNoCtor<T> &rhs) {
550 return !(lhs == rhs);
551}
552
553template<typename T>
554class InternalMmapVector : public InternalMmapVectorNoCtor<T> {
555 public:
556 InternalMmapVector() { InternalMmapVectorNoCtor<T>::Initialize(0); }
557 explicit InternalMmapVector(uptr cnt) {
558 InternalMmapVectorNoCtor<T>::Initialize(cnt);
559 this->resize(cnt);
560 }
561 ~InternalMmapVector() { InternalMmapVectorNoCtor<T>::Destroy(); }
562 // Disallow copies and moves.
563 InternalMmapVector(const InternalMmapVector &) = delete;
564 InternalMmapVector &operator=(const InternalMmapVector &) = delete;
565 InternalMmapVector(InternalMmapVector &&) = delete;
566 InternalMmapVector &operator=(InternalMmapVector &&) = delete;
567};
568
569class InternalScopedString : public InternalMmapVector<char> {
570 public:
571 explicit InternalScopedString(uptr max_length)
572 : InternalMmapVector<char>(max_length), length_(0) {
573 (*this)[0] = '\0';
574 }
575 uptr length() { return length_; }
576 void clear() {
577 (*this)[0] = '\0';
578 length_ = 0;
579 }
580 void append(const char *format, ...);
581
582 private:
583 uptr length_;
584};
585
586template <class T>
587struct CompareLess {
588 bool operator()(const T &a, const T &b) const { return a < b; }
589};
590
591// HeapSort for arrays and InternalMmapVector.
592template <class T, class Compare = CompareLess<T>>
593void Sort(T *v, uptr size, Compare comp = {}) {
594 if (size < 2)
595 return;
596 // Stage 1: insert elements to the heap.
597 for (uptr i = 1; i < size; i++) {
598 uptr j, p;
599 for (j = i; j > 0; j = p) {
600 p = (j - 1) / 2;
601 if (comp(v[p], v[j]))
602 Swap(v[j], v[p]);
603 else
604 break;
605 }
606 }
607 // Stage 2: swap largest element with the last one,
608 // and sink the new top.
609 for (uptr i = size - 1; i > 0; i--) {
610 Swap(v[0], v[i]);
611 uptr j, max_ind;
612 for (j = 0; j < i; j = max_ind) {
613 uptr left = 2 * j + 1;
614 uptr right = 2 * j + 2;
615 max_ind = j;
616 if (left < i && comp(v[max_ind], v[left]))
617 max_ind = left;
618 if (right < i && comp(v[max_ind], v[right]))
619 max_ind = right;
620 if (max_ind != j)
621 Swap(v[j], v[max_ind]);
622 else
623 break;
624 }
625 }
626}
627
628// Works like std::lower_bound: finds the first element that is not less
629// than the val.
630template <class Container, class Value, class Compare>
631uptr InternalLowerBound(const Container &v, uptr first, uptr last,
632 const Value &val, Compare comp) {
633 while (last > first) {
634 uptr mid = (first + last) / 2;
635 if (comp(v[mid], val))
636 first = mid + 1;
637 else
638 last = mid;
639 }
640 return first;
641}
642
643enum ModuleArch {
644 kModuleArchUnknown,
645 kModuleArchI386,
646 kModuleArchX86_64,
647 kModuleArchX86_64H,
648 kModuleArchARMV6,
649 kModuleArchARMV7,
650 kModuleArchARMV7S,
651 kModuleArchARMV7K,
652 kModuleArchARM64
653};
654
655// Opens the file 'file_name" and reads up to 'max_len' bytes.
656// The resulting buffer is mmaped and stored in '*buff'.
657// Returns true if file was successfully opened and read.
658bool ReadFileToVector(const char *file_name,
659 InternalMmapVectorNoCtor<char> *buff,
660 uptr max_len = 1 << 26, error_t *errno_p = nullptr);
661
662// Opens the file 'file_name" and reads up to 'max_len' bytes.
663// This function is less I/O efficient than ReadFileToVector as it may reread
664// file multiple times to avoid mmap during read attempts. It's used to read
665// procmap, so short reads with mmap in between can produce inconsistent result.
666// The resulting buffer is mmaped and stored in '*buff'.
667// The size of the mmaped region is stored in '*buff_size'.
668// The total number of read bytes is stored in '*read_len'.
669// Returns true if file was successfully opened and read.
670bool ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size,
671 uptr *read_len, uptr max_len = 1 << 26,
672 error_t *errno_p = nullptr);
673
674// When adding a new architecture, don't forget to also update
675// script/asan_symbolize.py and sanitizer_symbolizer_libcdep.cpp.
676inline const char *ModuleArchToString(ModuleArch arch) {
677 switch (arch) {
678 case kModuleArchUnknown:
679 return "";
680 case kModuleArchI386:
681 return "i386";
682 case kModuleArchX86_64:
683 return "x86_64";
684 case kModuleArchX86_64H:
685 return "x86_64h";
686 case kModuleArchARMV6:
687 return "armv6";
688 case kModuleArchARMV7:
689 return "armv7";
690 case kModuleArchARMV7S:
691 return "armv7s";
692 case kModuleArchARMV7K:
693 return "armv7k";
694 case kModuleArchARM64:
695 return "arm64";
696 }
697 CHECK(0 && "Invalid module arch");
698 return "";
699}
700
701const uptr kModuleUUIDSize = 16;
702const uptr kMaxSegName = 16;
703
704// Represents a binary loaded into virtual memory (e.g. this can be an
705// executable or a shared object).
706class LoadedModule {
707 public:
708 LoadedModule()
709 : full_name_(nullptr),
710 base_address_(0),
711 max_executable_address_(0),
712 arch_(kModuleArchUnknown),
713 instrumented_(false) {
714 internal_memset(uuid_, 0, kModuleUUIDSize);
715 ranges_.clear();
716 }
717 void set(const char *module_name, uptr base_address);
718 void set(const char *module_name, uptr base_address, ModuleArch arch,
719 u8 uuid[kModuleUUIDSize], bool instrumented);
720 void clear();
721 void addAddressRange(uptr beg, uptr end, bool executable, bool writable,
722 const char *name = nullptr);
723 bool containsAddress(uptr address) const;
724
725 const char *full_name() const { return full_name_; }
726 uptr base_address() const { return base_address_; }
727 uptr max_executable_address() const { return max_executable_address_; }
728 ModuleArch arch() const { return arch_; }
729 const u8 *uuid() const { return uuid_; }
730 bool instrumented() const { return instrumented_; }
731
732 struct AddressRange {
733 AddressRange *next;
734 uptr beg;
735 uptr end;
736 bool executable;
737 bool writable;
738 char name[kMaxSegName];
739
740 AddressRange(uptr beg, uptr end, bool executable, bool writable,
741 const char *name)
742 : next(nullptr),
743 beg(beg),
744 end(end),
745 executable(executable),
746 writable(writable) {
747 internal_strncpy(this->name, (name ? name : ""), ARRAY_SIZE(this->name));
748 }
749 };
750
751 const IntrusiveList<AddressRange> &ranges() const { return ranges_; }
752
753 private:
754 char *full_name_; // Owned.
755 uptr base_address_;
756 uptr max_executable_address_;
757 ModuleArch arch_;
758 u8 uuid_[kModuleUUIDSize];
759 bool instrumented_;
760 IntrusiveList<AddressRange> ranges_;
761};
762
763// List of LoadedModules. OS-dependent implementation is responsible for
764// filling this information.
765class ListOfModules {
766 public:
767 ListOfModules() : initialized(false) {}
768 ~ListOfModules() { clear(); }
769 void init();
770 void fallbackInit(); // Uses fallback init if available, otherwise clears
771 const LoadedModule *begin() const { return modules_.begin(); }
772 LoadedModule *begin() { return modules_.begin(); }
773 const LoadedModule *end() const { return modules_.end(); }
774 LoadedModule *end() { return modules_.end(); }
775 uptr size() const { return modules_.size(); }
776 const LoadedModule &operator[](uptr i) const {
777 CHECK_LT(i, modules_.size());
778 return modules_[i];
779 }
780
781 private:
782 void clear() {
783 for (auto &module : modules_) module.clear();
784 modules_.clear();
785 }
786 void clearOrInit() {
787 initialized ? clear() : modules_.Initialize(kInitialCapacity);
788 initialized = true;
789 }
790
791 InternalMmapVectorNoCtor<LoadedModule> modules_;
792 // We rarely have more than 16K loaded modules.
793 static const uptr kInitialCapacity = 1 << 14;
794 bool initialized;
795};
796
797// Callback type for iterating over a set of memory ranges.
798typedef void (*RangeIteratorCallback)(uptr begin, uptr end, void *arg);
799
800enum AndroidApiLevel {
801 ANDROID_NOT_ANDROID = 0,
802 ANDROID_KITKAT = 19,
803 ANDROID_LOLLIPOP_MR1 = 22,
804 ANDROID_POST_LOLLIPOP = 23
805};
806
807void WriteToSyslog(const char *buffer);
808
809#if defined(SANITIZER_WINDOWS) && defined(_MSC_VER) && !defined(__clang__)
810#define SANITIZER_WIN_TRACE 1
811#else
812#define SANITIZER_WIN_TRACE 0
813#endif
814
815#if SANITIZER_MAC || SANITIZER_WIN_TRACE
816void LogFullErrorReport(const char *buffer);
817#else
818INLINE void LogFullErrorReport(const char *buffer) {}
819#endif
820
821#if SANITIZER_LINUX || SANITIZER_MAC
822void WriteOneLineToSyslog(const char *s);
823void LogMessageOnPrintf(const char *str);
824#else
825INLINE void WriteOneLineToSyslog(const char *s) {}
826INLINE void LogMessageOnPrintf(const char *str) {}
827#endif
828
829#if SANITIZER_LINUX || SANITIZER_WIN_TRACE
830// Initialize Android logging. Any writes before this are silently lost.
831void AndroidLogInit();
832void SetAbortMessage(const char *);
833#else
834INLINE void AndroidLogInit() {}
835// FIXME: MacOS implementation could use CRSetCrashLogMessage.
836INLINE void SetAbortMessage(const char *) {}
837#endif
838
839#if SANITIZER_ANDROID
840void SanitizerInitializeUnwinder();
841AndroidApiLevel AndroidGetApiLevel();
842#else
843INLINE void AndroidLogWrite(const char *buffer_unused) {}
844INLINE void SanitizerInitializeUnwinder() {}
845INLINE AndroidApiLevel AndroidGetApiLevel() { return ANDROID_NOT_ANDROID; }
846#endif
847
848INLINE uptr GetPthreadDestructorIterations() {
849#if SANITIZER_ANDROID
850 return (AndroidGetApiLevel() == ANDROID_LOLLIPOP_MR1) ? 8 : 4;
851#elif SANITIZER_POSIX
852 return 4;
853#else
854// Unused on Windows.
855 return 0;
856#endif
857}
858
859void *internal_start_thread(void *(*func)(void*), void *arg);
860void internal_join_thread(void *th);
861void MaybeStartBackgroudThread();
862
863// Make the compiler think that something is going on there.
864// Use this inside a loop that looks like memset/memcpy/etc to prevent the
865// compiler from recognising it and turning it into an actual call to
866// memset/memcpy/etc.
867static inline void SanitizerBreakOptimization(void *arg) {
868#if defined(_MSC_VER) && !defined(__clang__)
869 _ReadWriteBarrier();
870#else
871 __asm__ __volatile__("" : : "r" (arg) : "memory");
872#endif
873}
874
875struct SignalContext {
876 void *siginfo;
877 void *context;
878 uptr addr;
879 uptr pc;
880 uptr sp;
881 uptr bp;
882 bool is_memory_access;
883 enum WriteFlag { UNKNOWN, READ, WRITE } write_flag;
884
885 // In some cases the kernel cannot provide the true faulting address; `addr`
886 // will be zero then. This field allows to distinguish between these cases
887 // and dereferences of null.
888 bool is_true_faulting_addr;
889
890 // VS2013 doesn't implement unrestricted unions, so we need a trivial default
891 // constructor
892 SignalContext() = default;
893
894 // Creates signal context in a platform-specific manner.
895 // SignalContext is going to keep pointers to siginfo and context without
896 // owning them.
897 SignalContext(void *siginfo, void *context)
898 : siginfo(siginfo),
899 context(context),
900 addr(GetAddress()),
901 is_memory_access(IsMemoryAccess()),
902 write_flag(GetWriteFlag()),
903 is_true_faulting_addr(IsTrueFaultingAddress()) {
904 InitPcSpBp();
905 }
906
907 static void DumpAllRegisters(void *context);
908
909 // Type of signal e.g. SIGSEGV or EXCEPTION_ACCESS_VIOLATION.
910 int GetType() const;
911
912 // String description of the signal.
913 const char *Describe() const;
914
915 // Returns true if signal is stack overflow.
916 bool IsStackOverflow() const;
917
918 private:
919 // Platform specific initialization.
920 void InitPcSpBp();
921 uptr GetAddress() const;
922 WriteFlag GetWriteFlag() const;
923 bool IsMemoryAccess() const;
924 bool IsTrueFaultingAddress() const;
925};
926
927void InitializePlatformEarly();
928void MaybeReexec();
929
930template <typename Fn>
931class RunOnDestruction {
932 public:
933 explicit RunOnDestruction(Fn fn) : fn_(fn) {}
934 ~RunOnDestruction() { fn_(); }
935
936 private:
937 Fn fn_;
938};
939
940// A simple scope guard. Usage:
941// auto cleanup = at_scope_exit([]{ do_cleanup; });
942template <typename Fn>
943RunOnDestruction<Fn> at_scope_exit(Fn fn) {
944 return RunOnDestruction<Fn>(fn);
945}
946
947// Linux on 64-bit s390 had a nasty bug that crashes the whole machine
948// if a process uses virtual memory over 4TB (as many sanitizers like
949// to do). This function will abort the process if running on a kernel
950// that looks vulnerable.
951#if SANITIZER_LINUX && SANITIZER_S390_64
952void AvoidCVE_2016_2143();
953#else
954INLINE void AvoidCVE_2016_2143() {}
955#endif
956
957struct StackDepotStats {
958 uptr n_uniq_ids;
959 uptr allocated;
960};
961
962// The default value for allocator_release_to_os_interval_ms common flag to
963// indicate that sanitizer allocator should not attempt to release memory to OS.
964const s32 kReleaseToOSIntervalNever = -1;
965
966void CheckNoDeepBind(const char *filename, int flag);
967
968// Returns the requested amount of random data (up to 256 bytes) that can then
969// be used to seed a PRNG. Defaults to blocking like the underlying syscall.
970bool GetRandom(void *buffer, uptr length, bool blocking = true);
971
972// Returns the number of logical processors on the system.
973u32 GetNumberOfCPUs();
974extern u32 NumberOfCPUsCached;
975INLINE u32 GetNumberOfCPUsCached() {
976 if (!NumberOfCPUsCached)
977 NumberOfCPUsCached = GetNumberOfCPUs();
978 return NumberOfCPUsCached;
979}
980
981template <typename T>
982class ArrayRef {
983 public:
984 ArrayRef() {}
985 ArrayRef(T *begin, T *end) : begin_(begin), end_(end) {}
986
987 T *begin() { return begin_; }
988 T *end() { return end_; }
989
990 private:
991 T *begin_ = nullptr;
992 T *end_ = nullptr;
993};
994
995} // namespace __sanitizer
996
997inline void *operator new(__sanitizer::operator_new_size_type size,
998 __sanitizer::LowLevelAllocator &alloc) { // NOLINT
999 return alloc.Allocate(size);
1000}
1001
1002#endif // SANITIZER_COMMON_H
lib/tsan/sanitizer_common/sanitizer_common_interceptors.inc created+10175
...@@ -0,0 +1,10175 @@
1//===-- sanitizer_common_interceptors.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// Common function interceptors for tools like AddressSanitizer,
10// ThreadSanitizer, MemorySanitizer, etc.
11//
12// This file should be included into the tool's interceptor file,
13// which has to define its own macros:
14// COMMON_INTERCEPTOR_ENTER
15// COMMON_INTERCEPTOR_ENTER_NOIGNORE
16// COMMON_INTERCEPTOR_READ_RANGE
17// COMMON_INTERCEPTOR_WRITE_RANGE
18// COMMON_INTERCEPTOR_INITIALIZE_RANGE
19// COMMON_INTERCEPTOR_DIR_ACQUIRE
20// COMMON_INTERCEPTOR_FD_ACQUIRE
21// COMMON_INTERCEPTOR_FD_RELEASE
22// COMMON_INTERCEPTOR_FD_ACCESS
23// COMMON_INTERCEPTOR_SET_THREAD_NAME
24// COMMON_INTERCEPTOR_ON_DLOPEN
25// 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
30// COMMON_INTERCEPTOR_SET_PTHREAD_NAME
31// COMMON_INTERCEPTOR_HANDLE_RECVMSG
32// COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED
33// COMMON_INTERCEPTOR_MEMSET_IMPL
34// COMMON_INTERCEPTOR_MEMMOVE_IMPL
35// COMMON_INTERCEPTOR_MEMCPY_IMPL
36// COMMON_INTERCEPTOR_MMAP_IMPL
37// COMMON_INTERCEPTOR_COPY_STRING
38// COMMON_INTERCEPTOR_STRNDUP_IMPL
39// COMMON_INTERCEPTOR_STRERROR
40//===----------------------------------------------------------------------===//
41
42#include "interception/interception.h"
43#include "sanitizer_addrhashmap.h"
44#include "sanitizer_errno.h"
45#include "sanitizer_placement_new.h"
46#include "sanitizer_platform_interceptors.h"
47#include "sanitizer_symbolizer.h"
48#include "sanitizer_tls_get_addr.h"
49
50#include <stdarg.h>
51
52#if SANITIZER_INTERCEPTOR_HOOKS
53#define CALL_WEAK_INTERCEPTOR_HOOK(f, ...) f(__VA_ARGS__);
54#define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...) \
55 SANITIZER_INTERFACE_WEAK_DEF(void, f, __VA_ARGS__) {}
56#else
57#define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...)
58#define CALL_WEAK_INTERCEPTOR_HOOK(f, ...)
59
60#endif // SANITIZER_INTERCEPTOR_HOOKS
61
62#if SANITIZER_WINDOWS && !defined(va_copy)
63#define va_copy(dst, src) ((dst) = (src))
64#endif // _WIN32
65
66#if SANITIZER_FREEBSD
67#define pthread_setname_np pthread_set_name_np
68#define inet_aton __inet_aton
69#define inet_pton __inet_pton
70#define iconv __bsd_iconv
71#endif
72
73#if SANITIZER_NETBSD
74#define clock_getres __clock_getres50
75#define clock_gettime __clock_gettime50
76#define clock_settime __clock_settime50
77#define ctime __ctime50
78#define ctime_r __ctime_r50
79#define devname __devname50
80#define fgetpos __fgetpos50
81#define fsetpos __fsetpos50
82#define fstatvfs __fstatvfs90
83#define fstatvfs1 __fstatvfs190
84#define fts_children __fts_children60
85#define fts_close __fts_close60
86#define fts_open __fts_open60
87#define fts_read __fts_read60
88#define fts_set __fts_set60
89#define getitimer __getitimer50
90#define getmntinfo __getmntinfo90
91#define getpwent __getpwent50
92#define getpwnam __getpwnam50
93#define getpwnam_r __getpwnam_r50
94#define getpwuid __getpwuid50
95#define getpwuid_r __getpwuid_r50
96#define getutent __getutent50
97#define getutxent __getutxent50
98#define getutxid __getutxid50
99#define getutxline __getutxline50
100#define getvfsstat __getvfsstat90
101#define pututxline __pututxline50
102#define glob __glob30
103#define gmtime __gmtime50
104#define gmtime_r __gmtime_r50
105#define localtime __locatime50
106#define localtime_r __localtime_r50
107#define mktime __mktime50
108#define lstat __lstat50
109#define opendir __opendir30
110#define readdir __readdir30
111#define readdir_r __readdir_r30
112#define scandir __scandir30
113#define setitimer __setitimer50
114#define setlocale __setlocale50
115#define shmctl __shmctl50
116#define sigaltstack __sigaltstack14
117#define sigemptyset __sigemptyset14
118#define sigfillset __sigfillset14
119#define sigpending __sigpending14
120#define sigprocmask __sigprocmask14
121#define sigtimedwait __sigtimedwait50
122#define stat __stat50
123#define statvfs __statvfs90
124#define statvfs1 __statvfs190
125#define time __time50
126#define times __times13
127#define unvis __unvis50
128#define wait3 __wait350
129#define wait4 __wait450
130extern const unsigned short *_ctype_tab_;
131extern const short *_toupper_tab_;
132extern const short *_tolower_tab_;
133#endif
134
135// Platform-specific options.
136#if SANITIZER_MAC
137#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE false
138#elif SANITIZER_WINDOWS64
139#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE false
140#else
141#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE true
142#endif // SANITIZER_MAC
143
144#ifndef COMMON_INTERCEPTOR_INITIALIZE_RANGE
145#define COMMON_INTERCEPTOR_INITIALIZE_RANGE(p, size) {}
146#endif
147
148#ifndef COMMON_INTERCEPTOR_UNPOISON_PARAM
149#define COMMON_INTERCEPTOR_UNPOISON_PARAM(count) {}
150#endif
151
152#ifndef COMMON_INTERCEPTOR_FD_ACCESS
153#define COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd) {}
154#endif
155
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
176#ifndef COMMON_INTERCEPTOR_HANDLE_RECVMSG
177#define COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg) ((void)(msg))
178#endif
179
180#ifndef COMMON_INTERCEPTOR_FILE_OPEN
181#define COMMON_INTERCEPTOR_FILE_OPEN(ctx, file, path) {}
182#endif
183
184#ifndef COMMON_INTERCEPTOR_FILE_CLOSE
185#define COMMON_INTERCEPTOR_FILE_CLOSE(ctx, file) {}
186#endif
187
188#ifndef COMMON_INTERCEPTOR_LIBRARY_LOADED
189#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) {}
190#endif
191
192#ifndef COMMON_INTERCEPTOR_LIBRARY_UNLOADED
193#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() {}
194#endif
195
196#ifndef COMMON_INTERCEPTOR_ENTER_NOIGNORE
197#define COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, ...) \
198 COMMON_INTERCEPTOR_ENTER(ctx, __VA_ARGS__)
199#endif
200
201#ifndef COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED
202#define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (0)
203#endif
204
205#define COMMON_INTERCEPTOR_READ_STRING(ctx, s, n) \
206 COMMON_INTERCEPTOR_READ_RANGE((ctx), (s), \
207 common_flags()->strict_string_checks ? (REAL(strlen)(s)) + 1 : (n) )
208
209#ifndef COMMON_INTERCEPTOR_ON_DLOPEN
210#define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag) \
211 CheckNoDeepBind(filename, flag);
212#endif
213
214#ifndef COMMON_INTERCEPTOR_GET_TLS_RANGE
215#define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) *begin = *end = 0;
216#endif
217
218#ifndef COMMON_INTERCEPTOR_ACQUIRE
219#define COMMON_INTERCEPTOR_ACQUIRE(ctx, u) {}
220#endif
221
222#ifndef COMMON_INTERCEPTOR_RELEASE
223#define COMMON_INTERCEPTOR_RELEASE(ctx, u) {}
224#endif
225
226#ifndef COMMON_INTERCEPTOR_USER_CALLBACK_START
227#define COMMON_INTERCEPTOR_USER_CALLBACK_START() {}
228#endif
229
230#ifndef COMMON_INTERCEPTOR_USER_CALLBACK_END
231#define COMMON_INTERCEPTOR_USER_CALLBACK_END() {}
232#endif
233
234#ifdef SANITIZER_NLDBL_VERSION
235#define COMMON_INTERCEPT_FUNCTION_LDBL(fn) \
236 COMMON_INTERCEPT_FUNCTION_VER(fn, SANITIZER_NLDBL_VERSION)
237#else
238#define COMMON_INTERCEPT_FUNCTION_LDBL(fn) \
239 COMMON_INTERCEPT_FUNCTION(fn)
240#endif
241
242#ifndef COMMON_INTERCEPTOR_MEMSET_IMPL
243#define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size) \
244 { \
245 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) \
246 return internal_memset(dst, v, size); \
247 COMMON_INTERCEPTOR_ENTER(ctx, memset, dst, v, size); \
248 if (common_flags()->intercept_intrin) \
249 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size); \
250 return REAL(memset)(dst, v, size); \
251 }
252#endif
253
254#ifndef COMMON_INTERCEPTOR_MEMMOVE_IMPL
255#define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size) \
256 { \
257 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) \
258 return internal_memmove(dst, src, size); \
259 COMMON_INTERCEPTOR_ENTER(ctx, memmove, dst, src, size); \
260 if (common_flags()->intercept_intrin) { \
261 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size); \
262 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size); \
263 } \
264 return REAL(memmove)(dst, src, size); \
265 }
266#endif
267
268#ifndef COMMON_INTERCEPTOR_MEMCPY_IMPL
269#define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, dst, src, size) \
270 { \
271 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) { \
272 return internal_memmove(dst, src, size); \
273 } \
274 COMMON_INTERCEPTOR_ENTER(ctx, memcpy, dst, src, size); \
275 if (common_flags()->intercept_intrin) { \
276 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size); \
277 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size); \
278 } \
279 return REAL(memcpy)(dst, src, size); \
280 }
281#endif
282
283#ifndef COMMON_INTERCEPTOR_MMAP_IMPL
284#define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, sz, prot, flags, fd, \
285 off) \
286 { return REAL(mmap)(addr, sz, prot, flags, fd, off); }
287#endif
288
289#ifndef COMMON_INTERCEPTOR_COPY_STRING
290#define COMMON_INTERCEPTOR_COPY_STRING(ctx, to, from, size) {}
291#endif
292
293#ifndef COMMON_INTERCEPTOR_STRNDUP_IMPL
294#define COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size) \
295 COMMON_INTERCEPTOR_ENTER(ctx, strndup, s, size); \
296 uptr copy_length = internal_strnlen(s, size); \
297 char *new_mem = (char *)WRAP(malloc)(copy_length + 1); \
298 if (common_flags()->intercept_strndup) { \
299 COMMON_INTERCEPTOR_READ_STRING(ctx, s, Min(size, copy_length + 1)); \
300 } \
301 COMMON_INTERCEPTOR_COPY_STRING(ctx, new_mem, s, copy_length); \
302 internal_memcpy(new_mem, s, copy_length); \
303 new_mem[copy_length] = '\0'; \
304 return new_mem;
305#endif
306
307#ifndef COMMON_INTERCEPTOR_STRERROR
308#define COMMON_INTERCEPTOR_STRERROR() {}
309#endif
310
311struct FileMetadata {
312 // For open_memstream().
313 char **addr;
314 SIZE_T *size;
315};
316
317struct CommonInterceptorMetadata {
318 enum {
319 CIMT_INVALID = 0,
320 CIMT_FILE
321 } type;
322 union {
323 FileMetadata file;
324 };
325};
326
327#if SI_POSIX
328typedef AddrHashMap<CommonInterceptorMetadata, 31051> MetadataHashMap;
329
330static MetadataHashMap *interceptor_metadata_map;
331
332UNUSED static void SetInterceptorMetadata(__sanitizer_FILE *addr,
333 const FileMetadata &file) {
334 MetadataHashMap::Handle h(interceptor_metadata_map, (uptr)addr);
335 CHECK(h.created());
336 h->type = CommonInterceptorMetadata::CIMT_FILE;
337 h->file = file;
338}
339
340UNUSED static const FileMetadata *GetInterceptorMetadata(
341 __sanitizer_FILE *addr) {
342 MetadataHashMap::Handle h(interceptor_metadata_map, (uptr)addr,
343 /* remove */ false,
344 /* create */ false);
345 if (addr && h.exists()) {
346 CHECK(!h.created());
347 CHECK(h->type == CommonInterceptorMetadata::CIMT_FILE);
348 return &h->file;
349 } else {
350 return 0;
351 }
352}
353
354UNUSED static void DeleteInterceptorMetadata(void *addr) {
355 MetadataHashMap::Handle h(interceptor_metadata_map, (uptr)addr, true);
356 CHECK(h.exists());
357}
358#endif // SI_POSIX
359
360#if SANITIZER_INTERCEPT_STRLEN
361INTERCEPTOR(SIZE_T, strlen, const char *s) {
362 // Sometimes strlen is called prior to InitializeCommonInterceptors,
363 // in which case the REAL(strlen) typically used in
364 // COMMON_INTERCEPTOR_ENTER will fail. We use internal_strlen here
365 // to handle that.
366 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
367 return internal_strlen(s);
368 void *ctx;
369 COMMON_INTERCEPTOR_ENTER(ctx, strlen, s);
370 SIZE_T result = REAL(strlen)(s);
371 if (common_flags()->intercept_strlen)
372 COMMON_INTERCEPTOR_READ_RANGE(ctx, s, result + 1);
373 return result;
374}
375#define INIT_STRLEN COMMON_INTERCEPT_FUNCTION(strlen)
376#else
377#define INIT_STRLEN
378#endif
379
380#if SANITIZER_INTERCEPT_STRNLEN
381INTERCEPTOR(SIZE_T, strnlen, const char *s, SIZE_T maxlen) {
382 void *ctx;
383 COMMON_INTERCEPTOR_ENTER(ctx, strnlen, s, maxlen);
384 SIZE_T length = REAL(strnlen)(s, maxlen);
385 if (common_flags()->intercept_strlen)
386 COMMON_INTERCEPTOR_READ_RANGE(ctx, s, Min(length + 1, maxlen));
387 return length;
388}
389#define INIT_STRNLEN COMMON_INTERCEPT_FUNCTION(strnlen)
390#else
391#define INIT_STRNLEN
392#endif
393
394#if SANITIZER_INTERCEPT_STRNDUP
395INTERCEPTOR(char*, strndup, const char *s, uptr size) {
396 void *ctx;
397 COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size);
398}
399#define INIT_STRNDUP COMMON_INTERCEPT_FUNCTION(strndup)
400#else
401#define INIT_STRNDUP
402#endif // SANITIZER_INTERCEPT_STRNDUP
403
404#if SANITIZER_INTERCEPT___STRNDUP
405INTERCEPTOR(char*, __strndup, const char *s, uptr size) {
406 void *ctx;
407 COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size);
408}
409#define INIT___STRNDUP COMMON_INTERCEPT_FUNCTION(__strndup)
410#else
411#define INIT___STRNDUP
412#endif // SANITIZER_INTERCEPT___STRNDUP
413
414#if SANITIZER_INTERCEPT_TEXTDOMAIN
415INTERCEPTOR(char*, textdomain, const char *domainname) {
416 void *ctx;
417 COMMON_INTERCEPTOR_ENTER(ctx, textdomain, domainname);
418 if (domainname) COMMON_INTERCEPTOR_READ_STRING(ctx, domainname, 0);
419 char *domain = REAL(textdomain)(domainname);
420 if (domain) {
421 COMMON_INTERCEPTOR_INITIALIZE_RANGE(domain, REAL(strlen)(domain) + 1);
422 }
423 return domain;
424}
425#define INIT_TEXTDOMAIN COMMON_INTERCEPT_FUNCTION(textdomain)
426#else
427#define INIT_TEXTDOMAIN
428#endif
429
430#if SANITIZER_INTERCEPT_STRCMP
431static inline int CharCmpX(unsigned char c1, unsigned char c2) {
432 return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
433}
434
435DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcmp, uptr called_pc,
436 const char *s1, const char *s2, int result)
437
438INTERCEPTOR(int, strcmp, const char *s1, const char *s2) {
439 void *ctx;
440 COMMON_INTERCEPTOR_ENTER(ctx, strcmp, s1, s2);
441 unsigned char c1, c2;
442 uptr i;
443 for (i = 0;; i++) {
444 c1 = (unsigned char)s1[i];
445 c2 = (unsigned char)s2[i];
446 if (c1 != c2 || c1 == '\0') break;
447 }
448 COMMON_INTERCEPTOR_READ_STRING(ctx, s1, i + 1);
449 COMMON_INTERCEPTOR_READ_STRING(ctx, s2, i + 1);
450 int result = CharCmpX(c1, c2);
451 CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcmp, GET_CALLER_PC(), s1,
452 s2, result);
453 return result;
454}
455
456DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncmp, uptr called_pc,
457 const char *s1, const char *s2, uptr n,
458 int result)
459
460INTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr size) {
461 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
462 return internal_strncmp(s1, s2, size);
463 void *ctx;
464 COMMON_INTERCEPTOR_ENTER(ctx, strncmp, s1, s2, size);
465 unsigned char c1 = 0, c2 = 0;
466 uptr i;
467 for (i = 0; i < size; i++) {
468 c1 = (unsigned char)s1[i];
469 c2 = (unsigned char)s2[i];
470 if (c1 != c2 || c1 == '\0') break;
471 }
472 uptr i1 = i;
473 uptr i2 = i;
474 if (common_flags()->strict_string_checks) {
475 for (; i1 < size && s1[i1]; i1++) {}
476 for (; i2 < size && s2[i2]; i2++) {}
477 }
478 COMMON_INTERCEPTOR_READ_RANGE((ctx), (s1), Min(i1 + 1, size));
479 COMMON_INTERCEPTOR_READ_RANGE((ctx), (s2), Min(i2 + 1, size));
480 int result = CharCmpX(c1, c2);
481 CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncmp, GET_CALLER_PC(), s1,
482 s2, size, result);
483 return result;
484}
485
486#define INIT_STRCMP COMMON_INTERCEPT_FUNCTION(strcmp)
487#define INIT_STRNCMP COMMON_INTERCEPT_FUNCTION(strncmp)
488#else
489#define INIT_STRCMP
490#define INIT_STRNCMP
491#endif
492
493#if SANITIZER_INTERCEPT_STRCASECMP
494static inline int CharCaseCmp(unsigned char c1, unsigned char c2) {
495 int c1_low = ToLower(c1);
496 int c2_low = ToLower(c2);
497 return c1_low - c2_low;
498}
499
500DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasecmp, uptr called_pc,
501 const char *s1, const char *s2, int result)
502
503INTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) {
504 void *ctx;
505 COMMON_INTERCEPTOR_ENTER(ctx, strcasecmp, s1, s2);
506 unsigned char c1 = 0, c2 = 0;
507 uptr i;
508 for (i = 0;; i++) {
509 c1 = (unsigned char)s1[i];
510 c2 = (unsigned char)s2[i];
511 if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
512 }
513 COMMON_INTERCEPTOR_READ_STRING(ctx, s1, i + 1);
514 COMMON_INTERCEPTOR_READ_STRING(ctx, s2, i + 1);
515 int result = CharCaseCmp(c1, c2);
516 CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasecmp, GET_CALLER_PC(),
517 s1, s2, result);
518 return result;
519}
520
521DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncasecmp, uptr called_pc,
522 const char *s1, const char *s2, uptr size,
523 int result)
524
525INTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, SIZE_T size) {
526 void *ctx;
527 COMMON_INTERCEPTOR_ENTER(ctx, strncasecmp, s1, s2, size);
528 unsigned char c1 = 0, c2 = 0;
529 uptr i;
530 for (i = 0; i < size; i++) {
531 c1 = (unsigned char)s1[i];
532 c2 = (unsigned char)s2[i];
533 if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
534 }
535 uptr i1 = i;
536 uptr i2 = i;
537 if (common_flags()->strict_string_checks) {
538 for (; i1 < size && s1[i1]; i1++) {}
539 for (; i2 < size && s2[i2]; i2++) {}
540 }
541 COMMON_INTERCEPTOR_READ_RANGE((ctx), (s1), Min(i1 + 1, size));
542 COMMON_INTERCEPTOR_READ_RANGE((ctx), (s2), Min(i2 + 1, size));
543 int result = CharCaseCmp(c1, c2);
544 CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncasecmp, GET_CALLER_PC(),
545 s1, s2, size, result);
546 return result;
547}
548
549#define INIT_STRCASECMP COMMON_INTERCEPT_FUNCTION(strcasecmp)
550#define INIT_STRNCASECMP COMMON_INTERCEPT_FUNCTION(strncasecmp)
551#else
552#define INIT_STRCASECMP
553#define INIT_STRNCASECMP
554#endif
555
556#if SANITIZER_INTERCEPT_STRSTR || SANITIZER_INTERCEPT_STRCASESTR
557static inline void StrstrCheck(void *ctx, char *r, const char *s1,
558 const char *s2) {
559 uptr len1 = REAL(strlen)(s1);
560 uptr len2 = REAL(strlen)(s2);
561 COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r ? r - s1 + len2 : len1 + 1);
562 COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, len2 + 1);
563}
564#endif
565
566#if SANITIZER_INTERCEPT_STRSTR
567
568DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strstr, uptr called_pc,
569 const char *s1, const char *s2, char *result)
570
571INTERCEPTOR(char*, strstr, const char *s1, const char *s2) {
572 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
573 return internal_strstr(s1, s2);
574 void *ctx;
575 COMMON_INTERCEPTOR_ENTER(ctx, strstr, s1, s2);
576 char *r = REAL(strstr)(s1, s2);
577 if (common_flags()->intercept_strstr)
578 StrstrCheck(ctx, r, s1, s2);
579 CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strstr, GET_CALLER_PC(), s1,
580 s2, r);
581 return r;
582}
583
584#define INIT_STRSTR COMMON_INTERCEPT_FUNCTION(strstr);
585#else
586#define INIT_STRSTR
587#endif
588
589#if SANITIZER_INTERCEPT_STRCASESTR
590
591DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasestr, uptr called_pc,
592 const char *s1, const char *s2, char *result)
593
594INTERCEPTOR(char*, strcasestr, const char *s1, const char *s2) {
595 void *ctx;
596 COMMON_INTERCEPTOR_ENTER(ctx, strcasestr, s1, s2);
597 char *r = REAL(strcasestr)(s1, s2);
598 if (common_flags()->intercept_strstr)
599 StrstrCheck(ctx, r, s1, s2);
600 CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasestr, GET_CALLER_PC(),
601 s1, s2, r);
602 return r;
603}
604
605#define INIT_STRCASESTR COMMON_INTERCEPT_FUNCTION(strcasestr);
606#else
607#define INIT_STRCASESTR
608#endif
609
610#if SANITIZER_INTERCEPT_STRTOK
611
612INTERCEPTOR(char*, strtok, char *str, const char *delimiters) {
613 void *ctx;
614 COMMON_INTERCEPTOR_ENTER(ctx, strtok, str, delimiters);
615 if (!common_flags()->intercept_strtok) {
616 return REAL(strtok)(str, delimiters);
617 }
618 if (common_flags()->strict_string_checks) {
619 // If strict_string_checks is enabled, we check the whole first argument
620 // string on the first call (strtok saves this string in a static buffer
621 // for subsequent calls). We do not need to check strtok's result.
622 // As the delimiters can change, we check them every call.
623 if (str != nullptr) {
624 COMMON_INTERCEPTOR_READ_RANGE(ctx, str, REAL(strlen)(str) + 1);
625 }
626 COMMON_INTERCEPTOR_READ_RANGE(ctx, delimiters,
627 REAL(strlen)(delimiters) + 1);
628 return REAL(strtok)(str, delimiters);
629 } else {
630 // However, when strict_string_checks is disabled we cannot check the
631 // whole string on the first call. Instead, we check the result string
632 // which is guaranteed to be a NULL-terminated substring of the first
633 // argument. We also conservatively check one character of str and the
634 // delimiters.
635 if (str != nullptr) {
636 COMMON_INTERCEPTOR_READ_STRING(ctx, str, 1);
637 }
638 COMMON_INTERCEPTOR_READ_RANGE(ctx, delimiters, 1);
639 char *result = REAL(strtok)(str, delimiters);
640 if (result != nullptr) {
641 COMMON_INTERCEPTOR_READ_RANGE(ctx, result, REAL(strlen)(result) + 1);
642 } else if (str != nullptr) {
643 // No delimiter were found, it's safe to assume that the entire str was
644 // scanned.
645 COMMON_INTERCEPTOR_READ_RANGE(ctx, str, REAL(strlen)(str) + 1);
646 }
647 return result;
648 }
649}
650
651#define INIT_STRTOK COMMON_INTERCEPT_FUNCTION(strtok)
652#else
653#define INIT_STRTOK
654#endif
655
656#if SANITIZER_INTERCEPT_MEMMEM
657DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memmem, uptr called_pc,
658 const void *s1, SIZE_T len1, const void *s2,
659 SIZE_T len2, void *result)
660
661INTERCEPTOR(void*, memmem, const void *s1, SIZE_T len1, const void *s2,
662 SIZE_T len2) {
663 void *ctx;
664 COMMON_INTERCEPTOR_ENTER(ctx, memmem, s1, len1, s2, len2);
665 void *r = REAL(memmem)(s1, len1, s2, len2);
666 if (common_flags()->intercept_memmem) {
667 COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, len1);
668 COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, len2);
669 }
670 CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memmem, GET_CALLER_PC(),
671 s1, len1, s2, len2, r);
672 return r;
673}
674
675#define INIT_MEMMEM COMMON_INTERCEPT_FUNCTION(memmem);
676#else
677#define INIT_MEMMEM
678#endif // SANITIZER_INTERCEPT_MEMMEM
679
680#if SANITIZER_INTERCEPT_STRCHR
681INTERCEPTOR(char*, strchr, const char *s, int c) {
682 void *ctx;
683 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
684 return internal_strchr(s, c);
685 COMMON_INTERCEPTOR_ENTER(ctx, strchr, s, c);
686 char *result = REAL(strchr)(s, c);
687 if (common_flags()->intercept_strchr) {
688 // Keep strlen as macro argument, as macro may ignore it.
689 COMMON_INTERCEPTOR_READ_STRING(ctx, s,
690 (result ? result - s : REAL(strlen)(s)) + 1);
691 }
692 return result;
693}
694#define INIT_STRCHR COMMON_INTERCEPT_FUNCTION(strchr)
695#else
696#define INIT_STRCHR
697#endif
698
699#if SANITIZER_INTERCEPT_STRCHRNUL
700INTERCEPTOR(char*, strchrnul, const char *s, int c) {
701 void *ctx;
702 COMMON_INTERCEPTOR_ENTER(ctx, strchrnul, s, c);
703 char *result = REAL(strchrnul)(s, c);
704 uptr len = result - s + 1;
705 if (common_flags()->intercept_strchr)
706 COMMON_INTERCEPTOR_READ_STRING(ctx, s, len);
707 return result;
708}
709#define INIT_STRCHRNUL COMMON_INTERCEPT_FUNCTION(strchrnul)
710#else
711#define INIT_STRCHRNUL
712#endif
713
714#if SANITIZER_INTERCEPT_STRRCHR
715INTERCEPTOR(char*, strrchr, const char *s, int c) {
716 void *ctx;
717 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
718 return internal_strrchr(s, c);
719 COMMON_INTERCEPTOR_ENTER(ctx, strrchr, s, c);
720 if (common_flags()->intercept_strchr)
721 COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
722 return REAL(strrchr)(s, c);
723}
724#define INIT_STRRCHR COMMON_INTERCEPT_FUNCTION(strrchr)
725#else
726#define INIT_STRRCHR
727#endif
728
729#if SANITIZER_INTERCEPT_STRSPN
730INTERCEPTOR(SIZE_T, strspn, const char *s1, const char *s2) {
731 void *ctx;
732 COMMON_INTERCEPTOR_ENTER(ctx, strspn, s1, s2);
733 SIZE_T r = REAL(strspn)(s1, s2);
734 if (common_flags()->intercept_strspn) {
735 COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, REAL(strlen)(s2) + 1);
736 COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r + 1);
737 }
738 return r;
739}
740
741INTERCEPTOR(SIZE_T, strcspn, const char *s1, const char *s2) {
742 void *ctx;
743 COMMON_INTERCEPTOR_ENTER(ctx, strcspn, s1, s2);
744 SIZE_T r = REAL(strcspn)(s1, s2);
745 if (common_flags()->intercept_strspn) {
746 COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, REAL(strlen)(s2) + 1);
747 COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r + 1);
748 }
749 return r;
750}
751
752#define INIT_STRSPN \
753 COMMON_INTERCEPT_FUNCTION(strspn); \
754 COMMON_INTERCEPT_FUNCTION(strcspn);
755#else
756#define INIT_STRSPN
757#endif
758
759#if SANITIZER_INTERCEPT_STRPBRK
760INTERCEPTOR(char *, strpbrk, const char *s1, const char *s2) {
761 void *ctx;
762 COMMON_INTERCEPTOR_ENTER(ctx, strpbrk, s1, s2);
763 char *r = REAL(strpbrk)(s1, s2);
764 if (common_flags()->intercept_strpbrk) {
765 COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, REAL(strlen)(s2) + 1);
766 COMMON_INTERCEPTOR_READ_STRING(ctx, s1,
767 r ? r - s1 + 1 : REAL(strlen)(s1) + 1);
768 }
769 return r;
770}
771
772#define INIT_STRPBRK COMMON_INTERCEPT_FUNCTION(strpbrk);
773#else
774#define INIT_STRPBRK
775#endif
776
777#if SANITIZER_INTERCEPT_MEMSET
778INTERCEPTOR(void *, memset, void *dst, int v, uptr size) {
779 void *ctx;
780 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size);
781}
782
783#define INIT_MEMSET COMMON_INTERCEPT_FUNCTION(memset)
784#else
785#define INIT_MEMSET
786#endif
787
788#if SANITIZER_INTERCEPT_MEMMOVE
789INTERCEPTOR(void *, memmove, void *dst, const void *src, uptr size) {
790 void *ctx;
791 COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size);
792}
793
794#define INIT_MEMMOVE COMMON_INTERCEPT_FUNCTION(memmove)
795#else
796#define INIT_MEMMOVE
797#endif
798
799#if SANITIZER_INTERCEPT_MEMCPY
800INTERCEPTOR(void *, memcpy, void *dst, const void *src, uptr size) {
801 // On OS X, calling internal_memcpy here will cause memory corruptions,
802 // because memcpy and memmove are actually aliases of the same
803 // implementation. We need to use internal_memmove here.
804 // N.B.: If we switch this to internal_ we'll have to use internal_memmove
805 // due to memcpy being an alias of memmove on OS X.
806 void *ctx;
807 if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
808 COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, dst, src, size);
809 } else {
810 COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size);
811 }
812}
813
814#define INIT_MEMCPY \
815 do { \
816 if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) { \
817 COMMON_INTERCEPT_FUNCTION(memcpy); \
818 } else { \
819 ASSIGN_REAL(memcpy, memmove); \
820 } \
821 CHECK(REAL(memcpy)); \
822 } while (false)
823
824#else
825#define INIT_MEMCPY
826#endif
827
828#if SANITIZER_INTERCEPT_MEMCMP
829DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, uptr called_pc,
830 const void *s1, const void *s2, uptr n,
831 int result)
832
833// Common code for `memcmp` and `bcmp`.
834int MemcmpInterceptorCommon(void *ctx,
835 int (*real_fn)(const void *, const void *, uptr),
836 const void *a1, const void *a2, uptr size) {
837 if (common_flags()->intercept_memcmp) {
838 if (common_flags()->strict_memcmp) {
839 // Check the entire regions even if the first bytes of the buffers are
840 // different.
841 COMMON_INTERCEPTOR_READ_RANGE(ctx, a1, size);
842 COMMON_INTERCEPTOR_READ_RANGE(ctx, a2, size);
843 // Fallthrough to REAL(memcmp) below.
844 } else {
845 unsigned char c1 = 0, c2 = 0;
846 const unsigned char *s1 = (const unsigned char*)a1;
847 const unsigned char *s2 = (const unsigned char*)a2;
848 uptr i;
849 for (i = 0; i < size; i++) {
850 c1 = s1[i];
851 c2 = s2[i];
852 if (c1 != c2) break;
853 }
854 COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, Min(i + 1, size));
855 COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, Min(i + 1, size));
856 int r = CharCmpX(c1, c2);
857 CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, GET_CALLER_PC(),
858 a1, a2, size, r);
859 return r;
860 }
861 }
862 int result = real_fn(a1, a2, size);
863 CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, GET_CALLER_PC(), a1,
864 a2, size, result);
865 return result;
866}
867
868INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
869 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
870 return internal_memcmp(a1, a2, size);
871 void *ctx;
872 COMMON_INTERCEPTOR_ENTER(ctx, memcmp, a1, a2, size);
873 return MemcmpInterceptorCommon(ctx, REAL(memcmp), a1, a2, size);
874}
875
876#define INIT_MEMCMP COMMON_INTERCEPT_FUNCTION(memcmp)
877#else
878#define INIT_MEMCMP
879#endif
880
881#if SANITIZER_INTERCEPT_BCMP
882INTERCEPTOR(int, bcmp, const void *a1, const void *a2, uptr size) {
883 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
884 return internal_memcmp(a1, a2, size);
885 void *ctx;
886 COMMON_INTERCEPTOR_ENTER(ctx, bcmp, a1, a2, size);
887 return MemcmpInterceptorCommon(ctx, REAL(bcmp), a1, a2, size);
888}
889
890#define INIT_BCMP COMMON_INTERCEPT_FUNCTION(bcmp)
891#else
892#define INIT_BCMP
893#endif
894
895#if SANITIZER_INTERCEPT_MEMCHR
896INTERCEPTOR(void*, memchr, const void *s, int c, SIZE_T n) {
897 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
898 return internal_memchr(s, c, n);
899 void *ctx;
900 COMMON_INTERCEPTOR_ENTER(ctx, memchr, s, c, n);
901#if SANITIZER_WINDOWS
902 void *res;
903 if (REAL(memchr)) {
904 res = REAL(memchr)(s, c, n);
905 } else {
906 res = internal_memchr(s, c, n);
907 }
908#else
909 void *res = REAL(memchr)(s, c, n);
910#endif
911 uptr len = res ? (char *)res - (const char *)s + 1 : n;
912 COMMON_INTERCEPTOR_READ_RANGE(ctx, s, len);
913 return res;
914}
915
916#define INIT_MEMCHR COMMON_INTERCEPT_FUNCTION(memchr)
917#else
918#define INIT_MEMCHR
919#endif
920
921#if SANITIZER_INTERCEPT_MEMRCHR
922INTERCEPTOR(void*, memrchr, const void *s, int c, SIZE_T n) {
923 void *ctx;
924 COMMON_INTERCEPTOR_ENTER(ctx, memrchr, s, c, n);
925 COMMON_INTERCEPTOR_READ_RANGE(ctx, s, n);
926 return REAL(memrchr)(s, c, n);
927}
928
929#define INIT_MEMRCHR COMMON_INTERCEPT_FUNCTION(memrchr)
930#else
931#define INIT_MEMRCHR
932#endif
933
934#if SANITIZER_INTERCEPT_FREXP
935INTERCEPTOR(double, frexp, double x, int *exp) {
936 void *ctx;
937 COMMON_INTERCEPTOR_ENTER(ctx, frexp, x, exp);
938 // Assuming frexp() always writes to |exp|.
939 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
940 double res = REAL(frexp)(x, exp);
941 return res;
942}
943
944#define INIT_FREXP COMMON_INTERCEPT_FUNCTION(frexp);
945#else
946#define INIT_FREXP
947#endif // SANITIZER_INTERCEPT_FREXP
948
949#if SANITIZER_INTERCEPT_FREXPF_FREXPL
950INTERCEPTOR(float, frexpf, float x, int *exp) {
951 void *ctx;
952 COMMON_INTERCEPTOR_ENTER(ctx, frexpf, x, exp);
953 // FIXME: under ASan the call below may write to freed memory and corrupt
954 // its metadata. See
955 // https://github.com/google/sanitizers/issues/321.
956 float res = REAL(frexpf)(x, exp);
957 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
958 return res;
959}
960
961INTERCEPTOR(long double, frexpl, long double x, int *exp) {
962 void *ctx;
963 COMMON_INTERCEPTOR_ENTER(ctx, frexpl, x, exp);
964 // FIXME: under ASan the call below may write to freed memory and corrupt
965 // its metadata. See
966 // https://github.com/google/sanitizers/issues/321.
967 long double res = REAL(frexpl)(x, exp);
968 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
969 return res;
970}
971
972#define INIT_FREXPF_FREXPL \
973 COMMON_INTERCEPT_FUNCTION(frexpf); \
974 COMMON_INTERCEPT_FUNCTION_LDBL(frexpl)
975#else
976#define INIT_FREXPF_FREXPL
977#endif // SANITIZER_INTERCEPT_FREXPF_FREXPL
978
979#if SI_POSIX
980static void write_iovec(void *ctx, struct __sanitizer_iovec *iovec,
981 SIZE_T iovlen, SIZE_T maxlen) {
982 for (SIZE_T i = 0; i < iovlen && maxlen; ++i) {
983 SSIZE_T sz = Min(iovec[i].iov_len, maxlen);
984 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iovec[i].iov_base, sz);
985 maxlen -= sz;
986 }
987}
988
989static void read_iovec(void *ctx, struct __sanitizer_iovec *iovec,
990 SIZE_T iovlen, SIZE_T maxlen) {
991 COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec, sizeof(*iovec) * iovlen);
992 for (SIZE_T i = 0; i < iovlen && maxlen; ++i) {
993 SSIZE_T sz = Min(iovec[i].iov_len, maxlen);
994 COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec[i].iov_base, sz);
995 maxlen -= sz;
996 }
997}
998#endif
999
1000#if SANITIZER_INTERCEPT_READ
1001INTERCEPTOR(SSIZE_T, read, int fd, void *ptr, SIZE_T count) {
1002 void *ctx;
1003 COMMON_INTERCEPTOR_ENTER(ctx, read, fd, ptr, count);
1004 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
1005 // FIXME: under ASan the call below may write to freed memory and corrupt
1006 // its metadata. See
1007 // https://github.com/google/sanitizers/issues/321.
1008 SSIZE_T res = REAL(read)(fd, ptr, count);
1009 if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
1010 if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
1011 return res;
1012}
1013#define INIT_READ COMMON_INTERCEPT_FUNCTION(read)
1014#else
1015#define INIT_READ
1016#endif
1017
1018#if SANITIZER_INTERCEPT_FREAD
1019INTERCEPTOR(SIZE_T, fread, void *ptr, SIZE_T size, SIZE_T nmemb, void *file) {
1020 // libc file streams can call user-supplied functions, see fopencookie.
1021 void *ctx;
1022 COMMON_INTERCEPTOR_ENTER(ctx, fread, ptr, size, nmemb, file);
1023 // FIXME: under ASan the call below may write to freed memory and corrupt
1024 // its metadata. See
1025 // https://github.com/google/sanitizers/issues/321.
1026 SIZE_T res = REAL(fread)(ptr, size, nmemb, file);
1027 if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res * size);
1028 return res;
1029}
1030#define INIT_FREAD COMMON_INTERCEPT_FUNCTION(fread)
1031#else
1032#define INIT_FREAD
1033#endif
1034
1035#if SANITIZER_INTERCEPT_PREAD
1036INTERCEPTOR(SSIZE_T, pread, int fd, void *ptr, SIZE_T count, OFF_T offset) {
1037 void *ctx;
1038 COMMON_INTERCEPTOR_ENTER(ctx, pread, fd, ptr, count, offset);
1039 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
1040 // FIXME: under ASan the call below may write to freed memory and corrupt
1041 // its metadata. See
1042 // https://github.com/google/sanitizers/issues/321.
1043 SSIZE_T res = REAL(pread)(fd, ptr, count, offset);
1044 if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
1045 if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
1046 return res;
1047}
1048#define INIT_PREAD COMMON_INTERCEPT_FUNCTION(pread)
1049#else
1050#define INIT_PREAD
1051#endif
1052
1053#if SANITIZER_INTERCEPT_PREAD64
1054INTERCEPTOR(SSIZE_T, pread64, int fd, void *ptr, SIZE_T count, OFF64_T offset) {
1055 void *ctx;
1056 COMMON_INTERCEPTOR_ENTER(ctx, pread64, fd, ptr, count, offset);
1057 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
1058 // FIXME: under ASan the call below may write to freed memory and corrupt
1059 // its metadata. See
1060 // https://github.com/google/sanitizers/issues/321.
1061 SSIZE_T res = REAL(pread64)(fd, ptr, count, offset);
1062 if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
1063 if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
1064 return res;
1065}
1066#define INIT_PREAD64 COMMON_INTERCEPT_FUNCTION(pread64)
1067#else
1068#define INIT_PREAD64
1069#endif
1070
1071#if SANITIZER_INTERCEPT_READV
1072INTERCEPTOR_WITH_SUFFIX(SSIZE_T, readv, int fd, __sanitizer_iovec *iov,
1073 int iovcnt) {
1074 void *ctx;
1075 COMMON_INTERCEPTOR_ENTER(ctx, readv, fd, iov, iovcnt);
1076 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
1077 SSIZE_T res = REAL(readv)(fd, iov, iovcnt);
1078 if (res > 0) write_iovec(ctx, iov, iovcnt, res);
1079 if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
1080 return res;
1081}
1082#define INIT_READV COMMON_INTERCEPT_FUNCTION(readv)
1083#else
1084#define INIT_READV
1085#endif
1086
1087#if SANITIZER_INTERCEPT_PREADV
1088INTERCEPTOR(SSIZE_T, preadv, int fd, __sanitizer_iovec *iov, int iovcnt,
1089 OFF_T offset) {
1090 void *ctx;
1091 COMMON_INTERCEPTOR_ENTER(ctx, preadv, fd, iov, iovcnt, offset);
1092 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
1093 SSIZE_T res = REAL(preadv)(fd, iov, iovcnt, offset);
1094 if (res > 0) write_iovec(ctx, iov, iovcnt, res);
1095 if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
1096 return res;
1097}
1098#define INIT_PREADV COMMON_INTERCEPT_FUNCTION(preadv)
1099#else
1100#define INIT_PREADV
1101#endif
1102
1103#if SANITIZER_INTERCEPT_PREADV64
1104INTERCEPTOR(SSIZE_T, preadv64, int fd, __sanitizer_iovec *iov, int iovcnt,
1105 OFF64_T offset) {
1106 void *ctx;
1107 COMMON_INTERCEPTOR_ENTER(ctx, preadv64, fd, iov, iovcnt, offset);
1108 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
1109 SSIZE_T res = REAL(preadv64)(fd, iov, iovcnt, offset);
1110 if (res > 0) write_iovec(ctx, iov, iovcnt, res);
1111 if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
1112 return res;
1113}
1114#define INIT_PREADV64 COMMON_INTERCEPT_FUNCTION(preadv64)
1115#else
1116#define INIT_PREADV64
1117#endif
1118
1119#if SANITIZER_INTERCEPT_WRITE
1120INTERCEPTOR(SSIZE_T, write, int fd, void *ptr, SIZE_T count) {
1121 void *ctx;
1122 COMMON_INTERCEPTOR_ENTER(ctx, write, fd, ptr, count);
1123 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
1124 if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
1125 SSIZE_T res = REAL(write)(fd, ptr, count);
1126 // FIXME: this check should be _before_ the call to REAL(write), not after
1127 if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
1128 return res;
1129}
1130#define INIT_WRITE COMMON_INTERCEPT_FUNCTION(write)
1131#else
1132#define INIT_WRITE
1133#endif
1134
1135#if SANITIZER_INTERCEPT_FWRITE
1136INTERCEPTOR(SIZE_T, fwrite, const void *p, uptr size, uptr nmemb, void *file) {
1137 // libc file streams can call user-supplied functions, see fopencookie.
1138 void *ctx;
1139 COMMON_INTERCEPTOR_ENTER(ctx, fwrite, p, size, nmemb, file);
1140 SIZE_T res = REAL(fwrite)(p, size, nmemb, file);
1141 if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, p, res * size);
1142 return res;
1143}
1144#define INIT_FWRITE COMMON_INTERCEPT_FUNCTION(fwrite)
1145#else
1146#define INIT_FWRITE
1147#endif
1148
1149#if SANITIZER_INTERCEPT_PWRITE
1150INTERCEPTOR(SSIZE_T, pwrite, int fd, void *ptr, SIZE_T count, OFF_T offset) {
1151 void *ctx;
1152 COMMON_INTERCEPTOR_ENTER(ctx, pwrite, fd, ptr, count, offset);
1153 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
1154 if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
1155 SSIZE_T res = REAL(pwrite)(fd, ptr, count, offset);
1156 if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
1157 return res;
1158}
1159#define INIT_PWRITE COMMON_INTERCEPT_FUNCTION(pwrite)
1160#else
1161#define INIT_PWRITE
1162#endif
1163
1164#if SANITIZER_INTERCEPT_PWRITE64
1165INTERCEPTOR(SSIZE_T, pwrite64, int fd, void *ptr, OFF64_T count,
1166 OFF64_T offset) {
1167 void *ctx;
1168 COMMON_INTERCEPTOR_ENTER(ctx, pwrite64, fd, ptr, count, offset);
1169 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
1170 if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
1171 SSIZE_T res = REAL(pwrite64)(fd, ptr, count, offset);
1172 if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
1173 return res;
1174}
1175#define INIT_PWRITE64 COMMON_INTERCEPT_FUNCTION(pwrite64)
1176#else
1177#define INIT_PWRITE64
1178#endif
1179
1180#if SANITIZER_INTERCEPT_WRITEV
1181INTERCEPTOR_WITH_SUFFIX(SSIZE_T, writev, int fd, __sanitizer_iovec *iov,
1182 int iovcnt) {
1183 void *ctx;
1184 COMMON_INTERCEPTOR_ENTER(ctx, writev, fd, iov, iovcnt);
1185 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
1186 if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
1187 SSIZE_T res = REAL(writev)(fd, iov, iovcnt);
1188 if (res > 0) read_iovec(ctx, iov, iovcnt, res);
1189 return res;
1190}
1191#define INIT_WRITEV COMMON_INTERCEPT_FUNCTION(writev)
1192#else
1193#define INIT_WRITEV
1194#endif
1195
1196#if SANITIZER_INTERCEPT_PWRITEV
1197INTERCEPTOR(SSIZE_T, pwritev, int fd, __sanitizer_iovec *iov, int iovcnt,
1198 OFF_T offset) {
1199 void *ctx;
1200 COMMON_INTERCEPTOR_ENTER(ctx, pwritev, fd, iov, iovcnt, offset);
1201 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
1202 if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
1203 SSIZE_T res = REAL(pwritev)(fd, iov, iovcnt, offset);
1204 if (res > 0) read_iovec(ctx, iov, iovcnt, res);
1205 return res;
1206}
1207#define INIT_PWRITEV COMMON_INTERCEPT_FUNCTION(pwritev)
1208#else
1209#define INIT_PWRITEV
1210#endif
1211
1212#if SANITIZER_INTERCEPT_PWRITEV64
1213INTERCEPTOR(SSIZE_T, pwritev64, int fd, __sanitizer_iovec *iov, int iovcnt,
1214 OFF64_T offset) {
1215 void *ctx;
1216 COMMON_INTERCEPTOR_ENTER(ctx, pwritev64, fd, iov, iovcnt, offset);
1217 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
1218 if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
1219 SSIZE_T res = REAL(pwritev64)(fd, iov, iovcnt, offset);
1220 if (res > 0) read_iovec(ctx, iov, iovcnt, res);
1221 return res;
1222}
1223#define INIT_PWRITEV64 COMMON_INTERCEPT_FUNCTION(pwritev64)
1224#else
1225#define INIT_PWRITEV64
1226#endif
1227
1228#if SANITIZER_INTERCEPT_FGETS
1229INTERCEPTOR(char *, fgets, char *s, SIZE_T size, void *file) {
1230 // libc file streams can call user-supplied functions, see fopencookie.
1231 void *ctx;
1232 COMMON_INTERCEPTOR_ENTER(ctx, fgets, s, size, file);
1233 // FIXME: under ASan the call below may write to freed memory and corrupt
1234 // its metadata. See
1235 // https://github.com/google/sanitizers/issues/321.
1236 char *res = REAL(fgets)(s, size, file);
1237 if (res)
1238 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, REAL(strlen)(s) + 1);
1239 return res;
1240}
1241#define INIT_FGETS COMMON_INTERCEPT_FUNCTION(fgets)
1242#else
1243#define INIT_FGETS
1244#endif
1245
1246#if SANITIZER_INTERCEPT_FPUTS
1247INTERCEPTOR_WITH_SUFFIX(int, fputs, char *s, void *file) {
1248 // libc file streams can call user-supplied functions, see fopencookie.
1249 void *ctx;
1250 COMMON_INTERCEPTOR_ENTER(ctx, fputs, s, file);
1251 if (!SANITIZER_MAC || s) { // `fputs(NULL, file)` is supported on Darwin.
1252 COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
1253 }
1254 return REAL(fputs)(s, file);
1255}
1256#define INIT_FPUTS COMMON_INTERCEPT_FUNCTION(fputs)
1257#else
1258#define INIT_FPUTS
1259#endif
1260
1261#if SANITIZER_INTERCEPT_PUTS
1262INTERCEPTOR(int, puts, char *s) {
1263 // libc file streams can call user-supplied functions, see fopencookie.
1264 void *ctx;
1265 COMMON_INTERCEPTOR_ENTER(ctx, puts, s);
1266 if (!SANITIZER_MAC || s) { // `puts(NULL)` is supported on Darwin.
1267 COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
1268 }
1269 return REAL(puts)(s);
1270}
1271#define INIT_PUTS COMMON_INTERCEPT_FUNCTION(puts)
1272#else
1273#define INIT_PUTS
1274#endif
1275
1276#if SANITIZER_INTERCEPT_PRCTL
1277INTERCEPTOR(int, prctl, int option, unsigned long arg2, unsigned long arg3,
1278 unsigned long arg4, unsigned long arg5) {
1279 void *ctx;
1280 COMMON_INTERCEPTOR_ENTER(ctx, prctl, option, arg2, arg3, arg4, arg5);
1281 static const int PR_SET_NAME = 15;
1282 int res = REAL(prctl(option, arg2, arg3, arg4, arg5));
1283 if (option == PR_SET_NAME) {
1284 char buff[16];
1285 internal_strncpy(buff, (char *)arg2, 15);
1286 buff[15] = 0;
1287 COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, buff);
1288 }
1289 return res;
1290}
1291#define INIT_PRCTL COMMON_INTERCEPT_FUNCTION(prctl)
1292#else
1293#define INIT_PRCTL
1294#endif // SANITIZER_INTERCEPT_PRCTL
1295
1296#if SANITIZER_INTERCEPT_TIME
1297INTERCEPTOR(unsigned long, time, unsigned long *t) {
1298 void *ctx;
1299 COMMON_INTERCEPTOR_ENTER(ctx, time, t);
1300 unsigned long local_t;
1301 unsigned long res = REAL(time)(&local_t);
1302 if (t && res != (unsigned long)-1) {
1303 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, t, sizeof(*t));
1304 *t = local_t;
1305 }
1306 return res;
1307}
1308#define INIT_TIME COMMON_INTERCEPT_FUNCTION(time);
1309#else
1310#define INIT_TIME
1311#endif // SANITIZER_INTERCEPT_TIME
1312
1313#if SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS
1314static void unpoison_tm(void *ctx, __sanitizer_tm *tm) {
1315 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tm, sizeof(*tm));
1316#if !SANITIZER_SOLARIS
1317 if (tm->tm_zone) {
1318 // Can not use COMMON_INTERCEPTOR_WRITE_RANGE here, because tm->tm_zone
1319 // can point to shared memory and tsan would report a data race.
1320 COMMON_INTERCEPTOR_INITIALIZE_RANGE(tm->tm_zone,
1321 REAL(strlen(tm->tm_zone)) + 1);
1322 }
1323#endif
1324}
1325INTERCEPTOR(__sanitizer_tm *, localtime, unsigned long *timep) {
1326 void *ctx;
1327 COMMON_INTERCEPTOR_ENTER(ctx, localtime, timep);
1328 __sanitizer_tm *res = REAL(localtime)(timep);
1329 if (res) {
1330 COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
1331 unpoison_tm(ctx, res);
1332 }
1333 return res;
1334}
1335INTERCEPTOR(__sanitizer_tm *, localtime_r, unsigned long *timep, void *result) {
1336 void *ctx;
1337 COMMON_INTERCEPTOR_ENTER(ctx, localtime_r, timep, result);
1338 __sanitizer_tm *res = REAL(localtime_r)(timep, result);
1339 if (res) {
1340 COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
1341 unpoison_tm(ctx, res);
1342 }
1343 return res;
1344}
1345INTERCEPTOR(__sanitizer_tm *, gmtime, unsigned long *timep) {
1346 void *ctx;
1347 COMMON_INTERCEPTOR_ENTER(ctx, gmtime, timep);
1348 __sanitizer_tm *res = REAL(gmtime)(timep);
1349 if (res) {
1350 COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
1351 unpoison_tm(ctx, res);
1352 }
1353 return res;
1354}
1355INTERCEPTOR(__sanitizer_tm *, gmtime_r, unsigned long *timep, void *result) {
1356 void *ctx;
1357 COMMON_INTERCEPTOR_ENTER(ctx, gmtime_r, timep, result);
1358 __sanitizer_tm *res = REAL(gmtime_r)(timep, result);
1359 if (res) {
1360 COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
1361 unpoison_tm(ctx, res);
1362 }
1363 return res;
1364}
1365INTERCEPTOR(char *, ctime, unsigned long *timep) {
1366 void *ctx;
1367 COMMON_INTERCEPTOR_ENTER(ctx, ctime, timep);
1368 // FIXME: under ASan the call below may write to freed memory and corrupt
1369 // its metadata. See
1370 // https://github.com/google/sanitizers/issues/321.
1371 char *res = REAL(ctime)(timep);
1372 if (res) {
1373 COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
1374 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1375 }
1376 return res;
1377}
1378INTERCEPTOR(char *, ctime_r, unsigned long *timep, char *result) {
1379 void *ctx;
1380 COMMON_INTERCEPTOR_ENTER(ctx, ctime_r, timep, result);
1381 // FIXME: under ASan the call below may write to freed memory and corrupt
1382 // its metadata. See
1383 // https://github.com/google/sanitizers/issues/321.
1384 char *res = REAL(ctime_r)(timep, result);
1385 if (res) {
1386 COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
1387 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1388 }
1389 return res;
1390}
1391INTERCEPTOR(char *, asctime, __sanitizer_tm *tm) {
1392 void *ctx;
1393 COMMON_INTERCEPTOR_ENTER(ctx, asctime, tm);
1394 // FIXME: under ASan the call below may write to freed memory and corrupt
1395 // its metadata. See
1396 // https://github.com/google/sanitizers/issues/321.
1397 char *res = REAL(asctime)(tm);
1398 if (res) {
1399 COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, sizeof(*tm));
1400 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1401 }
1402 return res;
1403}
1404INTERCEPTOR(char *, asctime_r, __sanitizer_tm *tm, char *result) {
1405 void *ctx;
1406 COMMON_INTERCEPTOR_ENTER(ctx, asctime_r, tm, result);
1407 // FIXME: under ASan the call below may write to freed memory and corrupt
1408 // its metadata. See
1409 // https://github.com/google/sanitizers/issues/321.
1410 char *res = REAL(asctime_r)(tm, result);
1411 if (res) {
1412 COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, sizeof(*tm));
1413 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
1414 }
1415 return res;
1416}
1417INTERCEPTOR(long, mktime, __sanitizer_tm *tm) {
1418 void *ctx;
1419 COMMON_INTERCEPTOR_ENTER(ctx, mktime, tm);
1420 COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_sec, sizeof(tm->tm_sec));
1421 COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_min, sizeof(tm->tm_min));
1422 COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_hour, sizeof(tm->tm_hour));
1423 COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_mday, sizeof(tm->tm_mday));
1424 COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_mon, sizeof(tm->tm_mon));
1425 COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_year, sizeof(tm->tm_year));
1426 COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_isdst, sizeof(tm->tm_isdst));
1427 long res = REAL(mktime)(tm);
1428 if (res != -1) unpoison_tm(ctx, tm);
1429 return res;
1430}
1431#define INIT_LOCALTIME_AND_FRIENDS \
1432 COMMON_INTERCEPT_FUNCTION(localtime); \
1433 COMMON_INTERCEPT_FUNCTION(localtime_r); \
1434 COMMON_INTERCEPT_FUNCTION(gmtime); \
1435 COMMON_INTERCEPT_FUNCTION(gmtime_r); \
1436 COMMON_INTERCEPT_FUNCTION(ctime); \
1437 COMMON_INTERCEPT_FUNCTION(ctime_r); \
1438 COMMON_INTERCEPT_FUNCTION(asctime); \
1439 COMMON_INTERCEPT_FUNCTION(asctime_r); \
1440 COMMON_INTERCEPT_FUNCTION(mktime);
1441#else
1442#define INIT_LOCALTIME_AND_FRIENDS
1443#endif // SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS
1444
1445#if SANITIZER_INTERCEPT_STRPTIME
1446INTERCEPTOR(char *, strptime, char *s, char *format, __sanitizer_tm *tm) {
1447 void *ctx;
1448 COMMON_INTERCEPTOR_ENTER(ctx, strptime, s, format, tm);
1449 if (format)
1450 COMMON_INTERCEPTOR_READ_RANGE(ctx, format, REAL(strlen)(format) + 1);
1451 // FIXME: under ASan the call below may write to freed memory and corrupt
1452 // its metadata. See
1453 // https://github.com/google/sanitizers/issues/321.
1454 char *res = REAL(strptime)(s, format, tm);
1455 COMMON_INTERCEPTOR_READ_STRING(ctx, s, res ? res - s : 0);
1456 if (res && tm) {
1457 // Do not call unpoison_tm here, because strptime does not, in fact,
1458 // initialize the entire struct tm. For example, tm_zone pointer is left
1459 // uninitialized.
1460 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tm, sizeof(*tm));
1461 }
1462 return res;
1463}
1464#define INIT_STRPTIME COMMON_INTERCEPT_FUNCTION(strptime);
1465#else
1466#define INIT_STRPTIME
1467#endif
1468
1469#if SANITIZER_INTERCEPT_SCANF || SANITIZER_INTERCEPT_PRINTF
1470#include "sanitizer_common_interceptors_format.inc"
1471
1472#define FORMAT_INTERCEPTOR_IMPL(name, vname, ...) \
1473 { \
1474 void *ctx; \
1475 va_list ap; \
1476 va_start(ap, format); \
1477 COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__, ap); \
1478 int res = WRAP(vname)(__VA_ARGS__, ap); \
1479 va_end(ap); \
1480 return res; \
1481 }
1482
1483#endif
1484
1485#if SANITIZER_INTERCEPT_SCANF
1486
1487#define VSCANF_INTERCEPTOR_IMPL(vname, allowGnuMalloc, ...) \
1488 { \
1489 void *ctx; \
1490 COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__); \
1491 va_list aq; \
1492 va_copy(aq, ap); \
1493 int res = REAL(vname)(__VA_ARGS__); \
1494 if (res > 0) \
1495 scanf_common(ctx, res, allowGnuMalloc, format, aq); \
1496 va_end(aq); \
1497 return res; \
1498 }
1499
1500INTERCEPTOR(int, vscanf, const char *format, va_list ap)
1501VSCANF_INTERCEPTOR_IMPL(vscanf, true, format, ap)
1502
1503INTERCEPTOR(int, vsscanf, const char *str, const char *format, va_list ap)
1504VSCANF_INTERCEPTOR_IMPL(vsscanf, true, str, format, ap)
1505
1506INTERCEPTOR(int, vfscanf, void *stream, const char *format, va_list ap)
1507VSCANF_INTERCEPTOR_IMPL(vfscanf, true, stream, format, ap)
1508
1509#if SANITIZER_INTERCEPT_ISOC99_SCANF
1510INTERCEPTOR(int, __isoc99_vscanf, const char *format, va_list ap)
1511VSCANF_INTERCEPTOR_IMPL(__isoc99_vscanf, false, format, ap)
1512
1513INTERCEPTOR(int, __isoc99_vsscanf, const char *str, const char *format,
1514 va_list ap)
1515VSCANF_INTERCEPTOR_IMPL(__isoc99_vsscanf, false, str, format, ap)
1516
1517INTERCEPTOR(int, __isoc99_vfscanf, void *stream, const char *format, va_list ap)
1518VSCANF_INTERCEPTOR_IMPL(__isoc99_vfscanf, false, stream, format, ap)
1519#endif // SANITIZER_INTERCEPT_ISOC99_SCANF
1520
1521INTERCEPTOR(int, scanf, const char *format, ...)
1522FORMAT_INTERCEPTOR_IMPL(scanf, vscanf, format)
1523
1524INTERCEPTOR(int, fscanf, void *stream, const char *format, ...)
1525FORMAT_INTERCEPTOR_IMPL(fscanf, vfscanf, stream, format)
1526
1527INTERCEPTOR(int, sscanf, const char *str, const char *format, ...)
1528FORMAT_INTERCEPTOR_IMPL(sscanf, vsscanf, str, format)
1529
1530#if SANITIZER_INTERCEPT_ISOC99_SCANF
1531INTERCEPTOR(int, __isoc99_scanf, const char *format, ...)
1532FORMAT_INTERCEPTOR_IMPL(__isoc99_scanf, __isoc99_vscanf, format)
1533
1534INTERCEPTOR(int, __isoc99_fscanf, void *stream, const char *format, ...)
1535FORMAT_INTERCEPTOR_IMPL(__isoc99_fscanf, __isoc99_vfscanf, stream, format)
1536
1537INTERCEPTOR(int, __isoc99_sscanf, const char *str, const char *format, ...)
1538FORMAT_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)
1539#endif
1540
1541#endif
1542
1543#if SANITIZER_INTERCEPT_SCANF
1544#define INIT_SCANF \
1545 COMMON_INTERCEPT_FUNCTION_LDBL(scanf); \
1546 COMMON_INTERCEPT_FUNCTION_LDBL(sscanf); \
1547 COMMON_INTERCEPT_FUNCTION_LDBL(fscanf); \
1548 COMMON_INTERCEPT_FUNCTION_LDBL(vscanf); \
1549 COMMON_INTERCEPT_FUNCTION_LDBL(vsscanf); \
1550 COMMON_INTERCEPT_FUNCTION_LDBL(vfscanf);
1551#else
1552#define INIT_SCANF
1553#endif
1554
1555#if SANITIZER_INTERCEPT_ISOC99_SCANF
1556#define INIT_ISOC99_SCANF \
1557 COMMON_INTERCEPT_FUNCTION(__isoc99_scanf); \
1558 COMMON_INTERCEPT_FUNCTION(__isoc99_sscanf); \
1559 COMMON_INTERCEPT_FUNCTION(__isoc99_fscanf); \
1560 COMMON_INTERCEPT_FUNCTION(__isoc99_vscanf); \
1561 COMMON_INTERCEPT_FUNCTION(__isoc99_vsscanf); \
1562 COMMON_INTERCEPT_FUNCTION(__isoc99_vfscanf);
1563#else
1564#define INIT_ISOC99_SCANF
1565#endif
1566
1567#if SANITIZER_INTERCEPT_PRINTF
1568
1569#define VPRINTF_INTERCEPTOR_ENTER(vname, ...) \
1570 void *ctx; \
1571 COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__); \
1572 va_list aq; \
1573 va_copy(aq, ap);
1574
1575#define VPRINTF_INTERCEPTOR_RETURN() \
1576 va_end(aq);
1577
1578#define VPRINTF_INTERCEPTOR_IMPL(vname, ...) \
1579 { \
1580 VPRINTF_INTERCEPTOR_ENTER(vname, __VA_ARGS__); \
1581 if (common_flags()->check_printf) \
1582 printf_common(ctx, format, aq); \
1583 int res = REAL(vname)(__VA_ARGS__); \
1584 VPRINTF_INTERCEPTOR_RETURN(); \
1585 return res; \
1586 }
1587
1588// FIXME: under ASan the REAL() call below may write to freed memory and
1589// corrupt its metadata. See
1590// https://github.com/google/sanitizers/issues/321.
1591#define VSPRINTF_INTERCEPTOR_IMPL(vname, str, ...) \
1592 { \
1593 VPRINTF_INTERCEPTOR_ENTER(vname, str, __VA_ARGS__) \
1594 if (common_flags()->check_printf) { \
1595 printf_common(ctx, format, aq); \
1596 } \
1597 int res = REAL(vname)(str, __VA_ARGS__); \
1598 if (res >= 0) { \
1599 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, str, res + 1); \
1600 } \
1601 VPRINTF_INTERCEPTOR_RETURN(); \
1602 return res; \
1603 }
1604
1605// FIXME: under ASan the REAL() call below may write to freed memory and
1606// corrupt its metadata. See
1607// https://github.com/google/sanitizers/issues/321.
1608#define VSNPRINTF_INTERCEPTOR_IMPL(vname, str, size, ...) \
1609 { \
1610 VPRINTF_INTERCEPTOR_ENTER(vname, str, size, __VA_ARGS__) \
1611 if (common_flags()->check_printf) { \
1612 printf_common(ctx, format, aq); \
1613 } \
1614 int res = REAL(vname)(str, size, __VA_ARGS__); \
1615 if (res >= 0) { \
1616 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, str, Min(size, (SIZE_T)(res + 1))); \
1617 } \
1618 VPRINTF_INTERCEPTOR_RETURN(); \
1619 return res; \
1620 }
1621
1622// FIXME: under ASan the REAL() call below may write to freed memory and
1623// corrupt its metadata. See
1624// https://github.com/google/sanitizers/issues/321.
1625#define VASPRINTF_INTERCEPTOR_IMPL(vname, strp, ...) \
1626 { \
1627 VPRINTF_INTERCEPTOR_ENTER(vname, strp, __VA_ARGS__) \
1628 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, strp, sizeof(char *)); \
1629 if (common_flags()->check_printf) { \
1630 printf_common(ctx, format, aq); \
1631 } \
1632 int res = REAL(vname)(strp, __VA_ARGS__); \
1633 if (res >= 0) { \
1634 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *strp, res + 1); \
1635 } \
1636 VPRINTF_INTERCEPTOR_RETURN(); \
1637 return res; \
1638 }
1639
1640INTERCEPTOR(int, vprintf, const char *format, va_list ap)
1641VPRINTF_INTERCEPTOR_IMPL(vprintf, format, ap)
1642
1643INTERCEPTOR(int, vfprintf, __sanitizer_FILE *stream, const char *format,
1644 va_list ap)
1645VPRINTF_INTERCEPTOR_IMPL(vfprintf, stream, format, ap)
1646
1647INTERCEPTOR(int, vsnprintf, char *str, SIZE_T size, const char *format,
1648 va_list ap)
1649VSNPRINTF_INTERCEPTOR_IMPL(vsnprintf, str, size, format, ap)
1650
1651#if SANITIZER_INTERCEPT___PRINTF_CHK
1652INTERCEPTOR(int, __vsnprintf_chk, char *str, SIZE_T size, int flag,
1653 SIZE_T size_to, const char *format, va_list ap)
1654VSNPRINTF_INTERCEPTOR_IMPL(vsnprintf, str, size, format, ap)
1655#endif
1656
1657#if SANITIZER_INTERCEPT_PRINTF_L
1658INTERCEPTOR(int, vsnprintf_l, char *str, SIZE_T size, void *loc,
1659 const char *format, va_list ap)
1660VSNPRINTF_INTERCEPTOR_IMPL(vsnprintf_l, str, size, loc, format, ap)
1661
1662INTERCEPTOR(int, snprintf_l, char *str, SIZE_T size, void *loc,
1663 const char *format, ...)
1664FORMAT_INTERCEPTOR_IMPL(snprintf_l, vsnprintf_l, str, size, loc, format)
1665#endif // SANITIZER_INTERCEPT_PRINTF_L
1666
1667INTERCEPTOR(int, vsprintf, char *str, const char *format, va_list ap)
1668VSPRINTF_INTERCEPTOR_IMPL(vsprintf, str, format, ap)
1669
1670#if SANITIZER_INTERCEPT___PRINTF_CHK
1671INTERCEPTOR(int, __vsprintf_chk, char *str, int flag, SIZE_T size_to,
1672 const char *format, va_list ap)
1673VSPRINTF_INTERCEPTOR_IMPL(vsprintf, str, format, ap)
1674#endif
1675
1676INTERCEPTOR(int, vasprintf, char **strp, const char *format, va_list ap)
1677VASPRINTF_INTERCEPTOR_IMPL(vasprintf, strp, format, ap)
1678
1679#if SANITIZER_INTERCEPT_ISOC99_PRINTF
1680INTERCEPTOR(int, __isoc99_vprintf, const char *format, va_list ap)
1681VPRINTF_INTERCEPTOR_IMPL(__isoc99_vprintf, format, ap)
1682
1683INTERCEPTOR(int, __isoc99_vfprintf, __sanitizer_FILE *stream,
1684 const char *format, va_list ap)
1685VPRINTF_INTERCEPTOR_IMPL(__isoc99_vfprintf, stream, format, ap)
1686
1687INTERCEPTOR(int, __isoc99_vsnprintf, char *str, SIZE_T size, const char *format,
1688 va_list ap)
1689VSNPRINTF_INTERCEPTOR_IMPL(__isoc99_vsnprintf, str, size, format, ap)
1690
1691INTERCEPTOR(int, __isoc99_vsprintf, char *str, const char *format,
1692 va_list ap)
1693VSPRINTF_INTERCEPTOR_IMPL(__isoc99_vsprintf, str, format,
1694 ap)
1695
1696#endif // SANITIZER_INTERCEPT_ISOC99_PRINTF
1697
1698INTERCEPTOR(int, printf, const char *format, ...)
1699FORMAT_INTERCEPTOR_IMPL(printf, vprintf, format)
1700
1701INTERCEPTOR(int, fprintf, __sanitizer_FILE *stream, const char *format, ...)
1702FORMAT_INTERCEPTOR_IMPL(fprintf, vfprintf, stream, format)
1703
1704#if SANITIZER_INTERCEPT___PRINTF_CHK
1705INTERCEPTOR(int, __fprintf_chk, __sanitizer_FILE *stream, SIZE_T size,
1706 const char *format, ...)
1707FORMAT_INTERCEPTOR_IMPL(__fprintf_chk, vfprintf, stream, format)
1708#endif
1709
1710INTERCEPTOR(int, sprintf, char *str, const char *format, ...)
1711FORMAT_INTERCEPTOR_IMPL(sprintf, vsprintf, str, format)
1712
1713#if SANITIZER_INTERCEPT___PRINTF_CHK
1714INTERCEPTOR(int, __sprintf_chk, char *str, int flag, SIZE_T size_to,
1715 const char *format, ...)
1716FORMAT_INTERCEPTOR_IMPL(__sprintf_chk, vsprintf, str, format)
1717#endif
1718
1719INTERCEPTOR(int, snprintf, char *str, SIZE_T size, const char *format, ...)
1720FORMAT_INTERCEPTOR_IMPL(snprintf, vsnprintf, str, size, format)
1721
1722#if SANITIZER_INTERCEPT___PRINTF_CHK
1723INTERCEPTOR(int, __snprintf_chk, char *str, SIZE_T size, int flag,
1724 SIZE_T size_to, const char *format, ...)
1725FORMAT_INTERCEPTOR_IMPL(__snprintf_chk, vsnprintf, str, size, format)
1726#endif
1727
1728INTERCEPTOR(int, asprintf, char **strp, const char *format, ...)
1729FORMAT_INTERCEPTOR_IMPL(asprintf, vasprintf, strp, format)
1730
1731#if SANITIZER_INTERCEPT_ISOC99_PRINTF
1732INTERCEPTOR(int, __isoc99_printf, const char *format, ...)
1733FORMAT_INTERCEPTOR_IMPL(__isoc99_printf, __isoc99_vprintf, format)
1734
1735INTERCEPTOR(int, __isoc99_fprintf, __sanitizer_FILE *stream, const char *format,
1736 ...)
1737FORMAT_INTERCEPTOR_IMPL(__isoc99_fprintf, __isoc99_vfprintf, stream, format)
1738
1739INTERCEPTOR(int, __isoc99_sprintf, char *str, const char *format, ...)
1740FORMAT_INTERCEPTOR_IMPL(__isoc99_sprintf, __isoc99_vsprintf, str, format)
1741
1742INTERCEPTOR(int, __isoc99_snprintf, char *str, SIZE_T size,
1743 const char *format, ...)
1744FORMAT_INTERCEPTOR_IMPL(__isoc99_snprintf, __isoc99_vsnprintf, str, size,
1745 format)
1746
1747#endif // SANITIZER_INTERCEPT_ISOC99_PRINTF
1748
1749#endif // SANITIZER_INTERCEPT_PRINTF
1750
1751#if SANITIZER_INTERCEPT_PRINTF
1752#define INIT_PRINTF \
1753 COMMON_INTERCEPT_FUNCTION_LDBL(printf); \
1754 COMMON_INTERCEPT_FUNCTION_LDBL(sprintf); \
1755 COMMON_INTERCEPT_FUNCTION_LDBL(snprintf); \
1756 COMMON_INTERCEPT_FUNCTION_LDBL(asprintf); \
1757 COMMON_INTERCEPT_FUNCTION_LDBL(fprintf); \
1758 COMMON_INTERCEPT_FUNCTION_LDBL(vprintf); \
1759 COMMON_INTERCEPT_FUNCTION_LDBL(vsprintf); \
1760 COMMON_INTERCEPT_FUNCTION_LDBL(vsnprintf); \
1761 COMMON_INTERCEPT_FUNCTION_LDBL(vasprintf); \
1762 COMMON_INTERCEPT_FUNCTION_LDBL(vfprintf);
1763#else
1764#define INIT_PRINTF
1765#endif
1766
1767#if SANITIZER_INTERCEPT___PRINTF_CHK
1768#define INIT___PRINTF_CHK \
1769 COMMON_INTERCEPT_FUNCTION(__sprintf_chk); \
1770 COMMON_INTERCEPT_FUNCTION(__snprintf_chk); \
1771 COMMON_INTERCEPT_FUNCTION(__vsprintf_chk); \
1772 COMMON_INTERCEPT_FUNCTION(__vsnprintf_chk); \
1773 COMMON_INTERCEPT_FUNCTION(__fprintf_chk);
1774#else
1775#define INIT___PRINTF_CHK
1776#endif
1777
1778#if SANITIZER_INTERCEPT_PRINTF_L
1779#define INIT_PRINTF_L \
1780 COMMON_INTERCEPT_FUNCTION(snprintf_l); \
1781 COMMON_INTERCEPT_FUNCTION(vsnprintf_l);
1782#else
1783#define INIT_PRINTF_L
1784#endif
1785
1786#if SANITIZER_INTERCEPT_ISOC99_PRINTF
1787#define INIT_ISOC99_PRINTF \
1788 COMMON_INTERCEPT_FUNCTION(__isoc99_printf); \
1789 COMMON_INTERCEPT_FUNCTION(__isoc99_sprintf); \
1790 COMMON_INTERCEPT_FUNCTION(__isoc99_snprintf); \
1791 COMMON_INTERCEPT_FUNCTION(__isoc99_fprintf); \
1792 COMMON_INTERCEPT_FUNCTION(__isoc99_vprintf); \
1793 COMMON_INTERCEPT_FUNCTION(__isoc99_vsprintf); \
1794 COMMON_INTERCEPT_FUNCTION(__isoc99_vsnprintf); \
1795 COMMON_INTERCEPT_FUNCTION(__isoc99_vfprintf);
1796#else
1797#define INIT_ISOC99_PRINTF
1798#endif
1799
1800#if SANITIZER_INTERCEPT_IOCTL
1801#include "sanitizer_common_interceptors_ioctl.inc"
1802#include "sanitizer_interceptors_ioctl_netbsd.inc"
1803INTERCEPTOR(int, ioctl, int d, unsigned long request, ...) {
1804 // We need a frame pointer, because we call into ioctl_common_[pre|post] which
1805 // can trigger a report and we need to be able to unwind through this
1806 // function. On Mac in debug mode we might not have a frame pointer, because
1807 // ioctl_common_[pre|post] doesn't get inlined here.
1808 ENABLE_FRAME_POINTER;
1809
1810 void *ctx;
1811 va_list ap;
1812 va_start(ap, request);
1813 void *arg = va_arg(ap, void *);
1814 va_end(ap);
1815 COMMON_INTERCEPTOR_ENTER(ctx, ioctl, d, request, arg);
1816
1817 CHECK(ioctl_initialized);
1818
1819 // Note: TSan does not use common flags, and they are zero-initialized.
1820 // This effectively disables ioctl handling in TSan.
1821 if (!common_flags()->handle_ioctl) return REAL(ioctl)(d, request, arg);
1822
1823 // Although request is unsigned long, the rest of the interceptor uses it
1824 // as just "unsigned" to save space, because we know that all values fit in
1825 // "unsigned" - they are compile-time constants.
1826
1827 const ioctl_desc *desc = ioctl_lookup(request);
1828 ioctl_desc decoded_desc;
1829 if (!desc) {
1830 VPrintf(2, "Decoding unknown ioctl 0x%x\n", request);
1831 if (!ioctl_decode(request, &decoded_desc))
1832 Printf("WARNING: failed decoding unknown ioctl 0x%x\n", request);
1833 else
1834 desc = &decoded_desc;
1835 }
1836
1837 if (desc) ioctl_common_pre(ctx, desc, d, request, arg);
1838 int res = REAL(ioctl)(d, request, arg);
1839 // FIXME: some ioctls have different return values for success and failure.
1840 if (desc && res != -1) ioctl_common_post(ctx, desc, res, d, request, arg);
1841 return res;
1842}
1843#define INIT_IOCTL \
1844 ioctl_init(); \
1845 COMMON_INTERCEPT_FUNCTION(ioctl);
1846#else
1847#define INIT_IOCTL
1848#endif
1849
1850#if SANITIZER_POSIX
1851UNUSED static void unpoison_passwd(void *ctx, __sanitizer_passwd *pwd) {
1852 if (pwd) {
1853 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd, sizeof(*pwd));
1854 if (pwd->pw_name)
1855 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_name,
1856 REAL(strlen)(pwd->pw_name) + 1);
1857 if (pwd->pw_passwd)
1858 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_passwd,
1859 REAL(strlen)(pwd->pw_passwd) + 1);
1860#if !SANITIZER_ANDROID
1861 if (pwd->pw_gecos)
1862 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_gecos,
1863 REAL(strlen)(pwd->pw_gecos) + 1);
1864#endif
1865#if SANITIZER_MAC || SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_OPENBSD
1866 if (pwd->pw_class)
1867 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_class,
1868 REAL(strlen)(pwd->pw_class) + 1);
1869#endif
1870 if (pwd->pw_dir)
1871 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_dir,
1872 REAL(strlen)(pwd->pw_dir) + 1);
1873 if (pwd->pw_shell)
1874 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_shell,
1875 REAL(strlen)(pwd->pw_shell) + 1);
1876 }
1877}
1878
1879UNUSED static void unpoison_group(void *ctx, __sanitizer_group *grp) {
1880 if (grp) {
1881 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp, sizeof(*grp));
1882 if (grp->gr_name)
1883 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp->gr_name,
1884 REAL(strlen)(grp->gr_name) + 1);
1885 if (grp->gr_passwd)
1886 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp->gr_passwd,
1887 REAL(strlen)(grp->gr_passwd) + 1);
1888 char **p = grp->gr_mem;
1889 for (; *p; ++p) {
1890 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
1891 }
1892 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp->gr_mem,
1893 (p - grp->gr_mem + 1) * sizeof(*p));
1894 }
1895}
1896#endif // SANITIZER_POSIX
1897
1898#if SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS
1899INTERCEPTOR(__sanitizer_passwd *, getpwnam, const char *name) {
1900 void *ctx;
1901 COMMON_INTERCEPTOR_ENTER(ctx, getpwnam, name);
1902 if (name)
1903 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
1904 __sanitizer_passwd *res = REAL(getpwnam)(name);
1905 unpoison_passwd(ctx, res);
1906 return res;
1907}
1908INTERCEPTOR(__sanitizer_passwd *, getpwuid, u32 uid) {
1909 void *ctx;
1910 COMMON_INTERCEPTOR_ENTER(ctx, getpwuid, uid);
1911 __sanitizer_passwd *res = REAL(getpwuid)(uid);
1912 unpoison_passwd(ctx, res);
1913 return res;
1914}
1915INTERCEPTOR(__sanitizer_group *, getgrnam, const char *name) {
1916 void *ctx;
1917 COMMON_INTERCEPTOR_ENTER(ctx, getgrnam, name);
1918 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
1919 __sanitizer_group *res = REAL(getgrnam)(name);
1920 unpoison_group(ctx, res);
1921 return res;
1922}
1923INTERCEPTOR(__sanitizer_group *, getgrgid, u32 gid) {
1924 void *ctx;
1925 COMMON_INTERCEPTOR_ENTER(ctx, getgrgid, gid);
1926 __sanitizer_group *res = REAL(getgrgid)(gid);
1927 unpoison_group(ctx, res);
1928 return res;
1929}
1930#define INIT_GETPWNAM_AND_FRIENDS \
1931 COMMON_INTERCEPT_FUNCTION(getpwnam); \
1932 COMMON_INTERCEPT_FUNCTION(getpwuid); \
1933 COMMON_INTERCEPT_FUNCTION(getgrnam); \
1934 COMMON_INTERCEPT_FUNCTION(getgrgid);
1935#else
1936#define INIT_GETPWNAM_AND_FRIENDS
1937#endif
1938
1939#if SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS
1940INTERCEPTOR(int, getpwnam_r, const char *name, __sanitizer_passwd *pwd,
1941 char *buf, SIZE_T buflen, __sanitizer_passwd **result) {
1942 void *ctx;
1943 COMMON_INTERCEPTOR_ENTER(ctx, getpwnam_r, name, pwd, buf, buflen, result);
1944 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
1945 // FIXME: under ASan the call below may write to freed memory and corrupt
1946 // its metadata. See
1947 // https://github.com/google/sanitizers/issues/321.
1948 int res = REAL(getpwnam_r)(name, pwd, buf, buflen, result);
1949 if (!res && result)
1950 unpoison_passwd(ctx, *result);
1951 if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1952 return res;
1953}
1954INTERCEPTOR(int, getpwuid_r, u32 uid, __sanitizer_passwd *pwd, char *buf,
1955 SIZE_T buflen, __sanitizer_passwd **result) {
1956 void *ctx;
1957 COMMON_INTERCEPTOR_ENTER(ctx, getpwuid_r, uid, pwd, buf, buflen, result);
1958 // FIXME: under ASan the call below may write to freed memory and corrupt
1959 // its metadata. See
1960 // https://github.com/google/sanitizers/issues/321.
1961 int res = REAL(getpwuid_r)(uid, pwd, buf, buflen, result);
1962 if (!res && result)
1963 unpoison_passwd(ctx, *result);
1964 if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1965 return res;
1966}
1967INTERCEPTOR(int, getgrnam_r, const char *name, __sanitizer_group *grp,
1968 char *buf, SIZE_T buflen, __sanitizer_group **result) {
1969 void *ctx;
1970 COMMON_INTERCEPTOR_ENTER(ctx, getgrnam_r, name, grp, buf, buflen, result);
1971 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
1972 // FIXME: under ASan the call below may write to freed memory and corrupt
1973 // its metadata. See
1974 // https://github.com/google/sanitizers/issues/321.
1975 int res = REAL(getgrnam_r)(name, grp, buf, buflen, result);
1976 if (!res && result)
1977 unpoison_group(ctx, *result);
1978 if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1979 return res;
1980}
1981INTERCEPTOR(int, getgrgid_r, u32 gid, __sanitizer_group *grp, char *buf,
1982 SIZE_T buflen, __sanitizer_group **result) {
1983 void *ctx;
1984 COMMON_INTERCEPTOR_ENTER(ctx, getgrgid_r, gid, grp, buf, buflen, result);
1985 // FIXME: under ASan the call below may write to freed memory and corrupt
1986 // its metadata. See
1987 // https://github.com/google/sanitizers/issues/321.
1988 int res = REAL(getgrgid_r)(gid, grp, buf, buflen, result);
1989 if (!res && result)
1990 unpoison_group(ctx, *result);
1991 if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
1992 return res;
1993}
1994#define INIT_GETPWNAM_R_AND_FRIENDS \
1995 COMMON_INTERCEPT_FUNCTION(getpwnam_r); \
1996 COMMON_INTERCEPT_FUNCTION(getpwuid_r); \
1997 COMMON_INTERCEPT_FUNCTION(getgrnam_r); \
1998 COMMON_INTERCEPT_FUNCTION(getgrgid_r);
1999#else
2000#define INIT_GETPWNAM_R_AND_FRIENDS
2001#endif
2002
2003#if SANITIZER_INTERCEPT_GETPWENT
2004INTERCEPTOR(__sanitizer_passwd *, getpwent, int dummy) {
2005 void *ctx;
2006 COMMON_INTERCEPTOR_ENTER(ctx, getpwent, dummy);
2007 __sanitizer_passwd *res = REAL(getpwent)(dummy);
2008 unpoison_passwd(ctx, res);
2009 return res;
2010}
2011INTERCEPTOR(__sanitizer_group *, getgrent, int dummy) {
2012 void *ctx;
2013 COMMON_INTERCEPTOR_ENTER(ctx, getgrent, dummy);
2014 __sanitizer_group *res = REAL(getgrent)(dummy);
2015 unpoison_group(ctx, res);
2016 return res;
2017}
2018#define INIT_GETPWENT \
2019 COMMON_INTERCEPT_FUNCTION(getpwent); \
2020 COMMON_INTERCEPT_FUNCTION(getgrent);
2021#else
2022#define INIT_GETPWENT
2023#endif
2024
2025#if SANITIZER_INTERCEPT_FGETPWENT
2026INTERCEPTOR(__sanitizer_passwd *, fgetpwent, void *fp) {
2027 void *ctx;
2028 COMMON_INTERCEPTOR_ENTER(ctx, fgetpwent, fp);
2029 __sanitizer_passwd *res = REAL(fgetpwent)(fp);
2030 unpoison_passwd(ctx, res);
2031 return res;
2032}
2033INTERCEPTOR(__sanitizer_group *, fgetgrent, void *fp) {
2034 void *ctx;
2035 COMMON_INTERCEPTOR_ENTER(ctx, fgetgrent, fp);
2036 __sanitizer_group *res = REAL(fgetgrent)(fp);
2037 unpoison_group(ctx, res);
2038 return res;
2039}
2040#define INIT_FGETPWENT \
2041 COMMON_INTERCEPT_FUNCTION(fgetpwent); \
2042 COMMON_INTERCEPT_FUNCTION(fgetgrent);
2043#else
2044#define INIT_FGETPWENT
2045#endif
2046
2047#if SANITIZER_INTERCEPT_GETPWENT_R
2048INTERCEPTOR(int, getpwent_r, __sanitizer_passwd *pwbuf, char *buf,
2049 SIZE_T buflen, __sanitizer_passwd **pwbufp) {
2050 void *ctx;
2051 COMMON_INTERCEPTOR_ENTER(ctx, getpwent_r, pwbuf, buf, buflen, pwbufp);
2052 // FIXME: under ASan the call below may write to freed memory and corrupt
2053 // its metadata. See
2054 // https://github.com/google/sanitizers/issues/321.
2055 int res = REAL(getpwent_r)(pwbuf, buf, buflen, pwbufp);
2056 if (!res && pwbufp)
2057 unpoison_passwd(ctx, *pwbufp);
2058 if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
2059 return res;
2060}
2061INTERCEPTOR(int, getgrent_r, __sanitizer_group *pwbuf, char *buf, SIZE_T buflen,
2062 __sanitizer_group **pwbufp) {
2063 void *ctx;
2064 COMMON_INTERCEPTOR_ENTER(ctx, getgrent_r, pwbuf, buf, buflen, pwbufp);
2065 // FIXME: under ASan the call below may write to freed memory and corrupt
2066 // its metadata. See
2067 // https://github.com/google/sanitizers/issues/321.
2068 int res = REAL(getgrent_r)(pwbuf, buf, buflen, pwbufp);
2069 if (!res && pwbufp)
2070 unpoison_group(ctx, *pwbufp);
2071 if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
2072 return res;
2073}
2074#define INIT_GETPWENT_R \
2075 COMMON_INTERCEPT_FUNCTION(getpwent_r); \
2076 COMMON_INTERCEPT_FUNCTION(getgrent_r);
2077#else
2078#define INIT_GETPWENT_R
2079#endif
2080
2081#if SANITIZER_INTERCEPT_FGETPWENT_R
2082INTERCEPTOR(int, fgetpwent_r, void *fp, __sanitizer_passwd *pwbuf, char *buf,
2083 SIZE_T buflen, __sanitizer_passwd **pwbufp) {
2084 void *ctx;
2085 COMMON_INTERCEPTOR_ENTER(ctx, fgetpwent_r, fp, pwbuf, buf, buflen, pwbufp);
2086 // FIXME: under ASan the call below may write to freed memory and corrupt
2087 // its metadata. See
2088 // https://github.com/google/sanitizers/issues/321.
2089 int res = REAL(fgetpwent_r)(fp, pwbuf, buf, buflen, pwbufp);
2090 if (!res && pwbufp)
2091 unpoison_passwd(ctx, *pwbufp);
2092 if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
2093 return res;
2094}
2095#define INIT_FGETPWENT_R \
2096 COMMON_INTERCEPT_FUNCTION(fgetpwent_r);
2097#else
2098#define INIT_FGETPWENT_R
2099#endif
2100
2101#if SANITIZER_INTERCEPT_FGETGRENT_R
2102INTERCEPTOR(int, fgetgrent_r, void *fp, __sanitizer_group *pwbuf, char *buf,
2103 SIZE_T buflen, __sanitizer_group **pwbufp) {
2104 void *ctx;
2105 COMMON_INTERCEPTOR_ENTER(ctx, fgetgrent_r, fp, pwbuf, buf, buflen, pwbufp);
2106 // FIXME: under ASan the call below may write to freed memory and corrupt
2107 // its metadata. See
2108 // https://github.com/google/sanitizers/issues/321.
2109 int res = REAL(fgetgrent_r)(fp, pwbuf, buf, buflen, pwbufp);
2110 if (!res && pwbufp)
2111 unpoison_group(ctx, *pwbufp);
2112 if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
2113 return res;
2114}
2115#define INIT_FGETGRENT_R \
2116 COMMON_INTERCEPT_FUNCTION(fgetgrent_r);
2117#else
2118#define INIT_FGETGRENT_R
2119#endif
2120
2121#if SANITIZER_INTERCEPT_SETPWENT
2122// The only thing these interceptors do is disable any nested interceptors.
2123// These functions may open nss modules and call uninstrumented functions from
2124// them, and we don't want things like strlen() to trigger.
2125INTERCEPTOR(void, setpwent, int dummy) {
2126 void *ctx;
2127 COMMON_INTERCEPTOR_ENTER(ctx, setpwent, dummy);
2128 REAL(setpwent)(dummy);
2129}
2130INTERCEPTOR(void, endpwent, int dummy) {
2131 void *ctx;
2132 COMMON_INTERCEPTOR_ENTER(ctx, endpwent, dummy);
2133 REAL(endpwent)(dummy);
2134}
2135INTERCEPTOR(void, setgrent, int dummy) {
2136 void *ctx;
2137 COMMON_INTERCEPTOR_ENTER(ctx, setgrent, dummy);
2138 REAL(setgrent)(dummy);
2139}
2140INTERCEPTOR(void, endgrent, int dummy) {
2141 void *ctx;
2142 COMMON_INTERCEPTOR_ENTER(ctx, endgrent, dummy);
2143 REAL(endgrent)(dummy);
2144}
2145#define INIT_SETPWENT \
2146 COMMON_INTERCEPT_FUNCTION(setpwent); \
2147 COMMON_INTERCEPT_FUNCTION(endpwent); \
2148 COMMON_INTERCEPT_FUNCTION(setgrent); \
2149 COMMON_INTERCEPT_FUNCTION(endgrent);
2150#else
2151#define INIT_SETPWENT
2152#endif
2153
2154#if SANITIZER_INTERCEPT_CLOCK_GETTIME
2155INTERCEPTOR(int, clock_getres, u32 clk_id, void *tp) {
2156 void *ctx;
2157 COMMON_INTERCEPTOR_ENTER(ctx, clock_getres, clk_id, tp);
2158 // FIXME: under ASan the call below may write to freed memory and corrupt
2159 // its metadata. See
2160 // https://github.com/google/sanitizers/issues/321.
2161 int res = REAL(clock_getres)(clk_id, tp);
2162 if (!res && tp) {
2163 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, struct_timespec_sz);
2164 }
2165 return res;
2166}
2167INTERCEPTOR(int, clock_gettime, u32 clk_id, void *tp) {
2168 void *ctx;
2169 COMMON_INTERCEPTOR_ENTER(ctx, clock_gettime, clk_id, tp);
2170 // FIXME: under ASan the call below may write to freed memory and corrupt
2171 // its metadata. See
2172 // https://github.com/google/sanitizers/issues/321.
2173 int res = REAL(clock_gettime)(clk_id, tp);
2174 if (!res) {
2175 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, struct_timespec_sz);
2176 }
2177 return res;
2178}
2179namespace __sanitizer {
2180extern "C" {
2181int real_clock_gettime(u32 clk_id, void *tp) {
2182 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
2183 return internal_clock_gettime(clk_id, tp);
2184 return REAL(clock_gettime)(clk_id, tp);
2185}
2186} // extern "C"
2187} // namespace __sanitizer
2188INTERCEPTOR(int, clock_settime, u32 clk_id, const void *tp) {
2189 void *ctx;
2190 COMMON_INTERCEPTOR_ENTER(ctx, clock_settime, clk_id, tp);
2191 COMMON_INTERCEPTOR_READ_RANGE(ctx, tp, struct_timespec_sz);
2192 return REAL(clock_settime)(clk_id, tp);
2193}
2194#define INIT_CLOCK_GETTIME \
2195 COMMON_INTERCEPT_FUNCTION(clock_getres); \
2196 COMMON_INTERCEPT_FUNCTION(clock_gettime); \
2197 COMMON_INTERCEPT_FUNCTION(clock_settime);
2198#else
2199#define INIT_CLOCK_GETTIME
2200#endif
2201
2202#if SANITIZER_INTERCEPT_CLOCK_GETCPUCLOCKID
2203INTERCEPTOR(int, clock_getcpuclockid, pid_t pid,
2204 __sanitizer_clockid_t *clockid) {
2205 void *ctx;
2206 COMMON_INTERCEPTOR_ENTER(ctx, clock_getcpuclockid, pid, clockid);
2207 int res = REAL(clock_getcpuclockid)(pid, clockid);
2208 if (!res && clockid) {
2209 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, clockid, sizeof *clockid);
2210 }
2211 return res;
2212}
2213
2214#define INIT_CLOCK_GETCPUCLOCKID \
2215 COMMON_INTERCEPT_FUNCTION(clock_getcpuclockid);
2216#else
2217#define INIT_CLOCK_GETCPUCLOCKID
2218#endif
2219
2220#if SANITIZER_INTERCEPT_GETITIMER
2221INTERCEPTOR(int, getitimer, int which, void *curr_value) {
2222 void *ctx;
2223 COMMON_INTERCEPTOR_ENTER(ctx, getitimer, which, curr_value);
2224 // FIXME: under ASan the call below may write to freed memory and corrupt
2225 // its metadata. See
2226 // https://github.com/google/sanitizers/issues/321.
2227 int res = REAL(getitimer)(which, curr_value);
2228 if (!res && curr_value) {
2229 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, curr_value, struct_itimerval_sz);
2230 }
2231 return res;
2232}
2233INTERCEPTOR(int, setitimer, int which, const void *new_value, void *old_value) {
2234 void *ctx;
2235 COMMON_INTERCEPTOR_ENTER(ctx, setitimer, which, new_value, old_value);
2236 if (new_value) {
2237 // itimerval can contain padding that may be legitimately uninitialized
2238 const struct __sanitizer_itimerval *nv =
2239 (const struct __sanitizer_itimerval *)new_value;
2240 COMMON_INTERCEPTOR_READ_RANGE(ctx, &nv->it_interval.tv_sec,
2241 sizeof(__sanitizer_time_t));
2242 COMMON_INTERCEPTOR_READ_RANGE(ctx, &nv->it_interval.tv_usec,
2243 sizeof(__sanitizer_suseconds_t));
2244 COMMON_INTERCEPTOR_READ_RANGE(ctx, &nv->it_value.tv_sec,
2245 sizeof(__sanitizer_time_t));
2246 COMMON_INTERCEPTOR_READ_RANGE(ctx, &nv->it_value.tv_usec,
2247 sizeof(__sanitizer_suseconds_t));
2248 }
2249 // FIXME: under ASan the call below may write to freed memory and corrupt
2250 // its metadata. See
2251 // https://github.com/google/sanitizers/issues/321.
2252 int res = REAL(setitimer)(which, new_value, old_value);
2253 if (!res && old_value) {
2254 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, old_value, struct_itimerval_sz);
2255 }
2256 return res;
2257}
2258#define INIT_GETITIMER \
2259 COMMON_INTERCEPT_FUNCTION(getitimer); \
2260 COMMON_INTERCEPT_FUNCTION(setitimer);
2261#else
2262#define INIT_GETITIMER
2263#endif
2264
2265#if SANITIZER_INTERCEPT_GLOB
2266static void unpoison_glob_t(void *ctx, __sanitizer_glob_t *pglob) {
2267 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pglob, sizeof(*pglob));
2268 // +1 for NULL pointer at the end.
2269 if (pglob->gl_pathv)
2270 COMMON_INTERCEPTOR_WRITE_RANGE(
2271 ctx, pglob->gl_pathv, (pglob->gl_pathc + 1) * sizeof(*pglob->gl_pathv));
2272 for (SIZE_T i = 0; i < pglob->gl_pathc; ++i) {
2273 char *p = pglob->gl_pathv[i];
2274 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, REAL(strlen)(p) + 1);
2275 }
2276}
2277
2278#if SANITIZER_SOLARIS
2279INTERCEPTOR(int, glob, const char *pattern, int flags,
2280 int (*errfunc)(const char *epath, int eerrno),
2281 __sanitizer_glob_t *pglob) {
2282 void *ctx;
2283 COMMON_INTERCEPTOR_ENTER(ctx, glob, pattern, flags, errfunc, pglob);
2284 COMMON_INTERCEPTOR_READ_STRING(ctx, pattern, 0);
2285 int res = REAL(glob)(pattern, flags, errfunc, pglob);
2286 if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
2287 return res;
2288}
2289#else
2290static THREADLOCAL __sanitizer_glob_t *pglob_copy;
2291
2292static void wrapped_gl_closedir(void *dir) {
2293 COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
2294 pglob_copy->gl_closedir(dir);
2295}
2296
2297static void *wrapped_gl_readdir(void *dir) {
2298 COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
2299 return pglob_copy->gl_readdir(dir);
2300}
2301
2302static void *wrapped_gl_opendir(const char *s) {
2303 COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
2304 COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, REAL(strlen)(s) + 1);
2305 return pglob_copy->gl_opendir(s);
2306}
2307
2308static int wrapped_gl_lstat(const char *s, void *st) {
2309 COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
2310 COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, REAL(strlen)(s) + 1);
2311 return pglob_copy->gl_lstat(s, st);
2312}
2313
2314static int wrapped_gl_stat(const char *s, void *st) {
2315 COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
2316 COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, REAL(strlen)(s) + 1);
2317 return pglob_copy->gl_stat(s, st);
2318}
2319
2320static const __sanitizer_glob_t kGlobCopy = {
2321 0, 0, 0,
2322 0, wrapped_gl_closedir, wrapped_gl_readdir,
2323 wrapped_gl_opendir, wrapped_gl_lstat, wrapped_gl_stat};
2324
2325INTERCEPTOR(int, glob, const char *pattern, int flags,
2326 int (*errfunc)(const char *epath, int eerrno),
2327 __sanitizer_glob_t *pglob) {
2328 void *ctx;
2329 COMMON_INTERCEPTOR_ENTER(ctx, glob, pattern, flags, errfunc, pglob);
2330 COMMON_INTERCEPTOR_READ_STRING(ctx, pattern, 0);
2331 __sanitizer_glob_t glob_copy;
2332 internal_memcpy(&glob_copy, &kGlobCopy, sizeof(glob_copy));
2333 if (flags & glob_altdirfunc) {
2334 Swap(pglob->gl_closedir, glob_copy.gl_closedir);
2335 Swap(pglob->gl_readdir, glob_copy.gl_readdir);
2336 Swap(pglob->gl_opendir, glob_copy.gl_opendir);
2337 Swap(pglob->gl_lstat, glob_copy.gl_lstat);
2338 Swap(pglob->gl_stat, glob_copy.gl_stat);
2339 pglob_copy = &glob_copy;
2340 }
2341 int res = REAL(glob)(pattern, flags, errfunc, pglob);
2342 if (flags & glob_altdirfunc) {
2343 Swap(pglob->gl_closedir, glob_copy.gl_closedir);
2344 Swap(pglob->gl_readdir, glob_copy.gl_readdir);
2345 Swap(pglob->gl_opendir, glob_copy.gl_opendir);
2346 Swap(pglob->gl_lstat, glob_copy.gl_lstat);
2347 Swap(pglob->gl_stat, glob_copy.gl_stat);
2348 }
2349 pglob_copy = 0;
2350 if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
2351 return res;
2352}
2353#endif // SANITIZER_SOLARIS
2354#define INIT_GLOB \
2355 COMMON_INTERCEPT_FUNCTION(glob);
2356#else // SANITIZER_INTERCEPT_GLOB
2357#define INIT_GLOB
2358#endif // SANITIZER_INTERCEPT_GLOB
2359
2360#if SANITIZER_INTERCEPT_GLOB64
2361INTERCEPTOR(int, glob64, const char *pattern, int flags,
2362 int (*errfunc)(const char *epath, int eerrno),
2363 __sanitizer_glob_t *pglob) {
2364 void *ctx;
2365 COMMON_INTERCEPTOR_ENTER(ctx, glob64, pattern, flags, errfunc, pglob);
2366 COMMON_INTERCEPTOR_READ_STRING(ctx, pattern, 0);
2367 __sanitizer_glob_t glob_copy;
2368 internal_memcpy(&glob_copy, &kGlobCopy, sizeof(glob_copy));
2369 if (flags & glob_altdirfunc) {
2370 Swap(pglob->gl_closedir, glob_copy.gl_closedir);
2371 Swap(pglob->gl_readdir, glob_copy.gl_readdir);
2372 Swap(pglob->gl_opendir, glob_copy.gl_opendir);
2373 Swap(pglob->gl_lstat, glob_copy.gl_lstat);
2374 Swap(pglob->gl_stat, glob_copy.gl_stat);
2375 pglob_copy = &glob_copy;
2376 }
2377 int res = REAL(glob64)(pattern, flags, errfunc, pglob);
2378 if (flags & glob_altdirfunc) {
2379 Swap(pglob->gl_closedir, glob_copy.gl_closedir);
2380 Swap(pglob->gl_readdir, glob_copy.gl_readdir);
2381 Swap(pglob->gl_opendir, glob_copy.gl_opendir);
2382 Swap(pglob->gl_lstat, glob_copy.gl_lstat);
2383 Swap(pglob->gl_stat, glob_copy.gl_stat);
2384 }
2385 pglob_copy = 0;
2386 if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
2387 return res;
2388}
2389#define INIT_GLOB64 \
2390 COMMON_INTERCEPT_FUNCTION(glob64);
2391#else // SANITIZER_INTERCEPT_GLOB64
2392#define INIT_GLOB64
2393#endif // SANITIZER_INTERCEPT_GLOB64
2394
2395#if SANITIZER_INTERCEPT_WAIT
2396// According to sys/wait.h, wait(), waitid(), waitpid() may have symbol version
2397// suffixes on Darwin. See the declaration of INTERCEPTOR_WITH_SUFFIX for
2398// details.
2399INTERCEPTOR_WITH_SUFFIX(int, wait, int *status) {
2400 void *ctx;
2401 COMMON_INTERCEPTOR_ENTER(ctx, wait, status);
2402 // FIXME: under ASan the call below may write to freed memory and corrupt
2403 // its metadata. See
2404 // https://github.com/google/sanitizers/issues/321.
2405 int res = REAL(wait)(status);
2406 if (res != -1 && status)
2407 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
2408 return res;
2409}
2410// On FreeBSD id_t is always 64-bit wide.
2411#if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32)
2412INTERCEPTOR_WITH_SUFFIX(int, waitid, int idtype, long long id, void *infop,
2413 int options) {
2414#else
2415INTERCEPTOR_WITH_SUFFIX(int, waitid, int idtype, int id, void *infop,
2416 int options) {
2417#endif
2418 void *ctx;
2419 COMMON_INTERCEPTOR_ENTER(ctx, waitid, idtype, id, infop, options);
2420 // FIXME: under ASan the call below may write to freed memory and corrupt
2421 // its metadata. See
2422 // https://github.com/google/sanitizers/issues/321.
2423 int res = REAL(waitid)(idtype, id, infop, options);
2424 if (res != -1 && infop)
2425 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, infop, siginfo_t_sz);
2426 return res;
2427}
2428INTERCEPTOR_WITH_SUFFIX(int, waitpid, int pid, int *status, int options) {
2429 void *ctx;
2430 COMMON_INTERCEPTOR_ENTER(ctx, waitpid, pid, status, options);
2431 // FIXME: under ASan the call below may write to freed memory and corrupt
2432 // its metadata. See
2433 // https://github.com/google/sanitizers/issues/321.
2434 int res = REAL(waitpid)(pid, status, options);
2435 if (res != -1 && status)
2436 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
2437 return res;
2438}
2439INTERCEPTOR(int, wait3, int *status, int options, void *rusage) {
2440 void *ctx;
2441 COMMON_INTERCEPTOR_ENTER(ctx, wait3, status, options, rusage);
2442 // FIXME: under ASan the call below may write to freed memory and corrupt
2443 // its metadata. See
2444 // https://github.com/google/sanitizers/issues/321.
2445 int res = REAL(wait3)(status, options, rusage);
2446 if (res != -1) {
2447 if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
2448 if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
2449 }
2450 return res;
2451}
2452#if SANITIZER_ANDROID
2453INTERCEPTOR(int, __wait4, int pid, int *status, int options, void *rusage) {
2454 void *ctx;
2455 COMMON_INTERCEPTOR_ENTER(ctx, __wait4, pid, status, options, rusage);
2456 // FIXME: under ASan the call below may write to freed memory and corrupt
2457 // its metadata. See
2458 // https://github.com/google/sanitizers/issues/321.
2459 int res = REAL(__wait4)(pid, status, options, rusage);
2460 if (res != -1) {
2461 if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
2462 if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
2463 }
2464 return res;
2465}
2466#define INIT_WAIT4 COMMON_INTERCEPT_FUNCTION(__wait4);
2467#else
2468INTERCEPTOR(int, wait4, int pid, int *status, int options, void *rusage) {
2469 void *ctx;
2470 COMMON_INTERCEPTOR_ENTER(ctx, wait4, pid, status, options, rusage);
2471 // FIXME: under ASan the call below may write to freed memory and corrupt
2472 // its metadata. See
2473 // https://github.com/google/sanitizers/issues/321.
2474 int res = REAL(wait4)(pid, status, options, rusage);
2475 if (res != -1) {
2476 if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
2477 if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
2478 }
2479 return res;
2480}
2481#define INIT_WAIT4 COMMON_INTERCEPT_FUNCTION(wait4);
2482#endif // SANITIZER_ANDROID
2483#define INIT_WAIT \
2484 COMMON_INTERCEPT_FUNCTION(wait); \
2485 COMMON_INTERCEPT_FUNCTION(waitid); \
2486 COMMON_INTERCEPT_FUNCTION(waitpid); \
2487 COMMON_INTERCEPT_FUNCTION(wait3);
2488#else
2489#define INIT_WAIT
2490#define INIT_WAIT4
2491#endif
2492
2493#if SANITIZER_INTERCEPT_INET
2494INTERCEPTOR(char *, inet_ntop, int af, const void *src, char *dst, u32 size) {
2495 void *ctx;
2496 COMMON_INTERCEPTOR_ENTER(ctx, inet_ntop, af, src, dst, size);
2497 uptr sz = __sanitizer_in_addr_sz(af);
2498 if (sz) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sz);
2499 // FIXME: figure out read size based on the address family.
2500 // FIXME: under ASan the call below may write to freed memory and corrupt
2501 // its metadata. See
2502 // https://github.com/google/sanitizers/issues/321.
2503 char *res = REAL(inet_ntop)(af, src, dst, size);
2504 if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
2505 return res;
2506}
2507INTERCEPTOR(int, inet_pton, int af, const char *src, void *dst) {
2508 void *ctx;
2509 COMMON_INTERCEPTOR_ENTER(ctx, inet_pton, af, src, dst);
2510 COMMON_INTERCEPTOR_READ_STRING(ctx, src, 0);
2511 // FIXME: figure out read size based on the address family.
2512 // FIXME: under ASan the call below may write to freed memory and corrupt
2513 // its metadata. See
2514 // https://github.com/google/sanitizers/issues/321.
2515 int res = REAL(inet_pton)(af, src, dst);
2516 if (res == 1) {
2517 uptr sz = __sanitizer_in_addr_sz(af);
2518 if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sz);
2519 }
2520 return res;
2521}
2522#define INIT_INET \
2523 COMMON_INTERCEPT_FUNCTION(inet_ntop); \
2524 COMMON_INTERCEPT_FUNCTION(inet_pton);
2525#else
2526#define INIT_INET
2527#endif
2528
2529#if SANITIZER_INTERCEPT_INET
2530INTERCEPTOR(int, inet_aton, const char *cp, void *dst) {
2531 void *ctx;
2532 COMMON_INTERCEPTOR_ENTER(ctx, inet_aton, cp, dst);
2533 if (cp) COMMON_INTERCEPTOR_READ_RANGE(ctx, cp, REAL(strlen)(cp) + 1);
2534 // FIXME: under ASan the call below may write to freed memory and corrupt
2535 // its metadata. See
2536 // https://github.com/google/sanitizers/issues/321.
2537 int res = REAL(inet_aton)(cp, dst);
2538 if (res != 0) {
2539 uptr sz = __sanitizer_in_addr_sz(af_inet);
2540 if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sz);
2541 }
2542 return res;
2543}
2544#define INIT_INET_ATON COMMON_INTERCEPT_FUNCTION(inet_aton);
2545#else
2546#define INIT_INET_ATON
2547#endif
2548
2549#if SANITIZER_INTERCEPT_PTHREAD_GETSCHEDPARAM
2550INTERCEPTOR(int, pthread_getschedparam, uptr thread, int *policy, int *param) {
2551 void *ctx;
2552 COMMON_INTERCEPTOR_ENTER(ctx, pthread_getschedparam, thread, policy, param);
2553 // FIXME: under ASan the call below may write to freed memory and corrupt
2554 // its metadata. See
2555 // https://github.com/google/sanitizers/issues/321.
2556 int res = REAL(pthread_getschedparam)(thread, policy, param);
2557 if (res == 0) {
2558 if (policy) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, policy, sizeof(*policy));
2559 if (param) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, param, sizeof(*param));
2560 }
2561 return res;
2562}
2563#define INIT_PTHREAD_GETSCHEDPARAM \
2564 COMMON_INTERCEPT_FUNCTION(pthread_getschedparam);
2565#else
2566#define INIT_PTHREAD_GETSCHEDPARAM
2567#endif
2568
2569#if SANITIZER_INTERCEPT_GETADDRINFO
2570INTERCEPTOR(int, getaddrinfo, char *node, char *service,
2571 struct __sanitizer_addrinfo *hints,
2572 struct __sanitizer_addrinfo **out) {
2573 void *ctx;
2574 COMMON_INTERCEPTOR_ENTER(ctx, getaddrinfo, node, service, hints, out);
2575 if (node) COMMON_INTERCEPTOR_READ_RANGE(ctx, node, REAL(strlen)(node) + 1);
2576 if (service)
2577 COMMON_INTERCEPTOR_READ_RANGE(ctx, service, REAL(strlen)(service) + 1);
2578 if (hints)
2579 COMMON_INTERCEPTOR_READ_RANGE(ctx, hints, sizeof(__sanitizer_addrinfo));
2580 // FIXME: under ASan the call below may write to freed memory and corrupt
2581 // its metadata. See
2582 // https://github.com/google/sanitizers/issues/321.
2583 int res = REAL(getaddrinfo)(node, service, hints, out);
2584 if (res == 0 && out) {
2585 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, out, sizeof(*out));
2586 struct __sanitizer_addrinfo *p = *out;
2587 while (p) {
2588 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
2589 if (p->ai_addr)
2590 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_addr, p->ai_addrlen);
2591 if (p->ai_canonname)
2592 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_canonname,
2593 REAL(strlen)(p->ai_canonname) + 1);
2594 p = p->ai_next;
2595 }
2596 }
2597 return res;
2598}
2599#define INIT_GETADDRINFO COMMON_INTERCEPT_FUNCTION(getaddrinfo);
2600#else
2601#define INIT_GETADDRINFO
2602#endif
2603
2604#if SANITIZER_INTERCEPT_GETNAMEINFO
2605INTERCEPTOR(int, getnameinfo, void *sockaddr, unsigned salen, char *host,
2606 unsigned hostlen, char *serv, unsigned servlen, int flags) {
2607 void *ctx;
2608 COMMON_INTERCEPTOR_ENTER(ctx, getnameinfo, sockaddr, salen, host, hostlen,
2609 serv, servlen, flags);
2610 // FIXME: consider adding READ_RANGE(sockaddr, salen)
2611 // There is padding in in_addr that may make this too noisy
2612 // FIXME: under ASan the call below may write to freed memory and corrupt
2613 // its metadata. See
2614 // https://github.com/google/sanitizers/issues/321.
2615 int res =
2616 REAL(getnameinfo)(sockaddr, salen, host, hostlen, serv, servlen, flags);
2617 if (res == 0) {
2618 if (host && hostlen)
2619 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, host, REAL(strlen)(host) + 1);
2620 if (serv && servlen)
2621 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, serv, REAL(strlen)(serv) + 1);
2622 }
2623 return res;
2624}
2625#define INIT_GETNAMEINFO COMMON_INTERCEPT_FUNCTION(getnameinfo);
2626#else
2627#define INIT_GETNAMEINFO
2628#endif
2629
2630#if SANITIZER_INTERCEPT_GETSOCKNAME
2631INTERCEPTOR(int, getsockname, int sock_fd, void *addr, int *addrlen) {
2632 void *ctx;
2633 COMMON_INTERCEPTOR_ENTER(ctx, getsockname, sock_fd, addr, addrlen);
2634 COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
2635 int addrlen_in = *addrlen;
2636 // FIXME: under ASan the call below may write to freed memory and corrupt
2637 // its metadata. See
2638 // https://github.com/google/sanitizers/issues/321.
2639 int res = REAL(getsockname)(sock_fd, addr, addrlen);
2640 if (res == 0) {
2641 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addrlen_in, *addrlen));
2642 }
2643 return res;
2644}
2645#define INIT_GETSOCKNAME COMMON_INTERCEPT_FUNCTION(getsockname);
2646#else
2647#define INIT_GETSOCKNAME
2648#endif
2649
2650#if SANITIZER_INTERCEPT_GETHOSTBYNAME || SANITIZER_INTERCEPT_GETHOSTBYNAME_R
2651static void write_hostent(void *ctx, struct __sanitizer_hostent *h) {
2652 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h, sizeof(__sanitizer_hostent));
2653 if (h->h_name)
2654 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h->h_name, REAL(strlen)(h->h_name) + 1);
2655 char **p = h->h_aliases;
2656 while (*p) {
2657 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
2658 ++p;
2659 }
2660 COMMON_INTERCEPTOR_WRITE_RANGE(
2661 ctx, h->h_aliases, (p - h->h_aliases + 1) * sizeof(*h->h_aliases));
2662 p = h->h_addr_list;
2663 while (*p) {
2664 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, h->h_length);
2665 ++p;
2666 }
2667 COMMON_INTERCEPTOR_WRITE_RANGE(
2668 ctx, h->h_addr_list, (p - h->h_addr_list + 1) * sizeof(*h->h_addr_list));
2669}
2670#endif
2671
2672#if SANITIZER_INTERCEPT_GETHOSTBYNAME
2673INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname, char *name) {
2674 void *ctx;
2675 COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname, name);
2676 struct __sanitizer_hostent *res = REAL(gethostbyname)(name);
2677 if (res) write_hostent(ctx, res);
2678 return res;
2679}
2680
2681INTERCEPTOR(struct __sanitizer_hostent *, gethostbyaddr, void *addr, int len,
2682 int type) {
2683 void *ctx;
2684 COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr, addr, len, type);
2685 COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
2686 struct __sanitizer_hostent *res = REAL(gethostbyaddr)(addr, len, type);
2687 if (res) write_hostent(ctx, res);
2688 return res;
2689}
2690
2691INTERCEPTOR(struct __sanitizer_hostent *, gethostent, int fake) {
2692 void *ctx;
2693 COMMON_INTERCEPTOR_ENTER(ctx, gethostent, fake);
2694 struct __sanitizer_hostent *res = REAL(gethostent)(fake);
2695 if (res) write_hostent(ctx, res);
2696 return res;
2697}
2698#define INIT_GETHOSTBYNAME \
2699 COMMON_INTERCEPT_FUNCTION(gethostent); \
2700 COMMON_INTERCEPT_FUNCTION(gethostbyaddr); \
2701 COMMON_INTERCEPT_FUNCTION(gethostbyname);
2702#else
2703#define INIT_GETHOSTBYNAME
2704#endif // SANITIZER_INTERCEPT_GETHOSTBYNAME
2705
2706#if SANITIZER_INTERCEPT_GETHOSTBYNAME2
2707INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname2, char *name, int af) {
2708 void *ctx;
2709 COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2, name, af);
2710 struct __sanitizer_hostent *res = REAL(gethostbyname2)(name, af);
2711 if (res) write_hostent(ctx, res);
2712 return res;
2713}
2714#define INIT_GETHOSTBYNAME2 COMMON_INTERCEPT_FUNCTION(gethostbyname2);
2715#else
2716#define INIT_GETHOSTBYNAME2
2717#endif // SANITIZER_INTERCEPT_GETHOSTBYNAME2
2718
2719#if SANITIZER_INTERCEPT_GETHOSTBYNAME_R
2720INTERCEPTOR(int, gethostbyname_r, char *name, struct __sanitizer_hostent *ret,
2721 char *buf, SIZE_T buflen, __sanitizer_hostent **result,
2722 int *h_errnop) {
2723 void *ctx;
2724 COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname_r, name, ret, buf, buflen, result,
2725 h_errnop);
2726 // FIXME: under ASan the call below may write to freed memory and corrupt
2727 // its metadata. See
2728 // https://github.com/google/sanitizers/issues/321.
2729 int res = REAL(gethostbyname_r)(name, ret, buf, buflen, result, h_errnop);
2730 if (result) {
2731 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
2732 if (res == 0 && *result) write_hostent(ctx, *result);
2733 }
2734 if (h_errnop)
2735 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
2736 return res;
2737}
2738#define INIT_GETHOSTBYNAME_R COMMON_INTERCEPT_FUNCTION(gethostbyname_r);
2739#else
2740#define INIT_GETHOSTBYNAME_R
2741#endif
2742
2743#if SANITIZER_INTERCEPT_GETHOSTENT_R
2744INTERCEPTOR(int, gethostent_r, struct __sanitizer_hostent *ret, char *buf,
2745 SIZE_T buflen, __sanitizer_hostent **result, int *h_errnop) {
2746 void *ctx;
2747 COMMON_INTERCEPTOR_ENTER(ctx, gethostent_r, ret, buf, buflen, result,
2748 h_errnop);
2749 // FIXME: under ASan the call below may write to freed memory and corrupt
2750 // its metadata. See
2751 // https://github.com/google/sanitizers/issues/321.
2752 int res = REAL(gethostent_r)(ret, buf, buflen, result, h_errnop);
2753 if (result) {
2754 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
2755 if (res == 0 && *result) write_hostent(ctx, *result);
2756 }
2757 if (h_errnop)
2758 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
2759 return res;
2760}
2761#define INIT_GETHOSTENT_R \
2762 COMMON_INTERCEPT_FUNCTION(gethostent_r);
2763#else
2764#define INIT_GETHOSTENT_R
2765#endif
2766
2767#if SANITIZER_INTERCEPT_GETHOSTBYADDR_R
2768INTERCEPTOR(int, gethostbyaddr_r, void *addr, int len, int type,
2769 struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
2770 __sanitizer_hostent **result, int *h_errnop) {
2771 void *ctx;
2772 COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr_r, addr, len, type, ret, buf,
2773 buflen, result, h_errnop);
2774 COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
2775 // FIXME: under ASan the call below may write to freed memory and corrupt
2776 // its metadata. See
2777 // https://github.com/google/sanitizers/issues/321.
2778 int res = REAL(gethostbyaddr_r)(addr, len, type, ret, buf, buflen, result,
2779 h_errnop);
2780 if (result) {
2781 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
2782 if (res == 0 && *result) write_hostent(ctx, *result);
2783 }
2784 if (h_errnop)
2785 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
2786 return res;
2787}
2788#define INIT_GETHOSTBYADDR_R \
2789 COMMON_INTERCEPT_FUNCTION(gethostbyaddr_r);
2790#else
2791#define INIT_GETHOSTBYADDR_R
2792#endif
2793
2794#if SANITIZER_INTERCEPT_GETHOSTBYNAME2_R
2795INTERCEPTOR(int, gethostbyname2_r, char *name, int af,
2796 struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
2797 __sanitizer_hostent **result, int *h_errnop) {
2798 void *ctx;
2799 COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2_r, name, af, ret, buf, buflen,
2800 result, h_errnop);
2801 // FIXME: under ASan the call below may write to freed memory and corrupt
2802 // its metadata. See
2803 // https://github.com/google/sanitizers/issues/321.
2804 int res =
2805 REAL(gethostbyname2_r)(name, af, ret, buf, buflen, result, h_errnop);
2806 if (result) {
2807 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
2808 if (res == 0 && *result) write_hostent(ctx, *result);
2809 }
2810 if (h_errnop)
2811 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
2812 return res;
2813}
2814#define INIT_GETHOSTBYNAME2_R \
2815 COMMON_INTERCEPT_FUNCTION(gethostbyname2_r);
2816#else
2817#define INIT_GETHOSTBYNAME2_R
2818#endif
2819
2820#if SANITIZER_INTERCEPT_GETSOCKOPT
2821INTERCEPTOR(int, getsockopt, int sockfd, int level, int optname, void *optval,
2822 int *optlen) {
2823 void *ctx;
2824 COMMON_INTERCEPTOR_ENTER(ctx, getsockopt, sockfd, level, optname, optval,
2825 optlen);
2826 if (optlen) COMMON_INTERCEPTOR_READ_RANGE(ctx, optlen, sizeof(*optlen));
2827 // FIXME: under ASan the call below may write to freed memory and corrupt
2828 // its metadata. See
2829 // https://github.com/google/sanitizers/issues/321.
2830 int res = REAL(getsockopt)(sockfd, level, optname, optval, optlen);
2831 if (res == 0)
2832 if (optval && optlen) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, optval, *optlen);
2833 return res;
2834}
2835#define INIT_GETSOCKOPT COMMON_INTERCEPT_FUNCTION(getsockopt);
2836#else
2837#define INIT_GETSOCKOPT
2838#endif
2839
2840#if SANITIZER_INTERCEPT_ACCEPT
2841INTERCEPTOR(int, accept, int fd, void *addr, unsigned *addrlen) {
2842 void *ctx;
2843 COMMON_INTERCEPTOR_ENTER(ctx, accept, fd, addr, addrlen);
2844 unsigned addrlen0 = 0;
2845 if (addrlen) {
2846 COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
2847 addrlen0 = *addrlen;
2848 }
2849 int fd2 = REAL(accept)(fd, addr, addrlen);
2850 if (fd2 >= 0) {
2851 if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
2852 if (addr && addrlen)
2853 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0));
2854 }
2855 return fd2;
2856}
2857#define INIT_ACCEPT COMMON_INTERCEPT_FUNCTION(accept);
2858#else
2859#define INIT_ACCEPT
2860#endif
2861
2862#if SANITIZER_INTERCEPT_ACCEPT4
2863INTERCEPTOR(int, accept4, int fd, void *addr, unsigned *addrlen, int f) {
2864 void *ctx;
2865 COMMON_INTERCEPTOR_ENTER(ctx, accept4, fd, addr, addrlen, f);
2866 unsigned addrlen0 = 0;
2867 if (addrlen) {
2868 COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
2869 addrlen0 = *addrlen;
2870 }
2871 // FIXME: under ASan the call below may write to freed memory and corrupt
2872 // its metadata. See
2873 // https://github.com/google/sanitizers/issues/321.
2874 int fd2 = REAL(accept4)(fd, addr, addrlen, f);
2875 if (fd2 >= 0) {
2876 if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
2877 if (addr && addrlen)
2878 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0));
2879 }
2880 return fd2;
2881}
2882#define INIT_ACCEPT4 COMMON_INTERCEPT_FUNCTION(accept4);
2883#else
2884#define INIT_ACCEPT4
2885#endif
2886
2887#if SANITIZER_INTERCEPT_PACCEPT
2888INTERCEPTOR(int, paccept, int fd, void *addr, unsigned *addrlen,
2889 __sanitizer_sigset_t *set, int f) {
2890 void *ctx;
2891 COMMON_INTERCEPTOR_ENTER(ctx, paccept, fd, addr, addrlen, set, f);
2892 unsigned addrlen0 = 0;
2893 if (addrlen) {
2894 COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
2895 addrlen0 = *addrlen;
2896 }
2897 if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
2898 int fd2 = REAL(paccept)(fd, addr, addrlen, set, f);
2899 if (fd2 >= 0) {
2900 if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
2901 if (addr && addrlen)
2902 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0));
2903 }
2904 return fd2;
2905}
2906#define INIT_PACCEPT COMMON_INTERCEPT_FUNCTION(paccept);
2907#else
2908#define INIT_PACCEPT
2909#endif
2910
2911#if SANITIZER_INTERCEPT_MODF
2912INTERCEPTOR(double, modf, double x, double *iptr) {
2913 void *ctx;
2914 COMMON_INTERCEPTOR_ENTER(ctx, modf, x, iptr);
2915 // FIXME: under ASan the call below may write to freed memory and corrupt
2916 // its metadata. See
2917 // https://github.com/google/sanitizers/issues/321.
2918 double res = REAL(modf)(x, iptr);
2919 if (iptr) {
2920 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
2921 }
2922 return res;
2923}
2924INTERCEPTOR(float, modff, float x, float *iptr) {
2925 void *ctx;
2926 COMMON_INTERCEPTOR_ENTER(ctx, modff, x, iptr);
2927 // FIXME: under ASan the call below may write to freed memory and corrupt
2928 // its metadata. See
2929 // https://github.com/google/sanitizers/issues/321.
2930 float res = REAL(modff)(x, iptr);
2931 if (iptr) {
2932 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
2933 }
2934 return res;
2935}
2936INTERCEPTOR(long double, modfl, long double x, long double *iptr) {
2937 void *ctx;
2938 COMMON_INTERCEPTOR_ENTER(ctx, modfl, x, iptr);
2939 // FIXME: under ASan the call below may write to freed memory and corrupt
2940 // its metadata. See
2941 // https://github.com/google/sanitizers/issues/321.
2942 long double res = REAL(modfl)(x, iptr);
2943 if (iptr) {
2944 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
2945 }
2946 return res;
2947}
2948#define INIT_MODF \
2949 COMMON_INTERCEPT_FUNCTION(modf); \
2950 COMMON_INTERCEPT_FUNCTION(modff); \
2951 COMMON_INTERCEPT_FUNCTION_LDBL(modfl);
2952#else
2953#define INIT_MODF
2954#endif
2955
2956#if SANITIZER_INTERCEPT_RECVMSG || SANITIZER_INTERCEPT_RECVMMSG
2957static void write_msghdr(void *ctx, struct __sanitizer_msghdr *msg,
2958 SSIZE_T maxlen) {
2959 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg, sizeof(*msg));
2960 if (msg->msg_name && msg->msg_namelen)
2961 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_name, msg->msg_namelen);
2962 if (msg->msg_iov && msg->msg_iovlen)
2963 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_iov,
2964 sizeof(*msg->msg_iov) * msg->msg_iovlen);
2965 write_iovec(ctx, msg->msg_iov, msg->msg_iovlen, maxlen);
2966 if (msg->msg_control && msg->msg_controllen)
2967 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_control, msg->msg_controllen);
2968}
2969#endif
2970
2971#if SANITIZER_INTERCEPT_RECVMSG
2972INTERCEPTOR(SSIZE_T, recvmsg, int fd, struct __sanitizer_msghdr *msg,
2973 int flags) {
2974 void *ctx;
2975 COMMON_INTERCEPTOR_ENTER(ctx, recvmsg, fd, msg, flags);
2976 // FIXME: under ASan the call below may write to freed memory and corrupt
2977 // its metadata. See
2978 // https://github.com/google/sanitizers/issues/321.
2979 SSIZE_T res = REAL(recvmsg)(fd, msg, flags);
2980 if (res >= 0) {
2981 if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
2982 if (msg) {
2983 write_msghdr(ctx, msg, res);
2984 COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg);
2985 }
2986 }
2987 return res;
2988}
2989#define INIT_RECVMSG COMMON_INTERCEPT_FUNCTION(recvmsg);
2990#else
2991#define INIT_RECVMSG
2992#endif
2993
2994#if SANITIZER_INTERCEPT_RECVMMSG
2995INTERCEPTOR(int, recvmmsg, int fd, struct __sanitizer_mmsghdr *msgvec,
2996 unsigned int vlen, int flags, void *timeout) {
2997 void *ctx;
2998 COMMON_INTERCEPTOR_ENTER(ctx, recvmmsg, fd, msgvec, vlen, flags, timeout);
2999 if (timeout) COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout, struct_timespec_sz);
3000 int res = REAL(recvmmsg)(fd, msgvec, vlen, flags, timeout);
3001 if (res >= 0) {
3002 if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
3003 for (int i = 0; i < res; ++i) {
3004 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &msgvec[i].msg_len,
3005 sizeof(msgvec[i].msg_len));
3006 write_msghdr(ctx, &msgvec[i].msg_hdr, msgvec[i].msg_len);
3007 COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, &msgvec[i].msg_hdr);
3008 }
3009 }
3010 return res;
3011}
3012#define INIT_RECVMMSG COMMON_INTERCEPT_FUNCTION(recvmmsg);
3013#else
3014#define INIT_RECVMMSG
3015#endif
3016
3017#if SANITIZER_INTERCEPT_SENDMSG || SANITIZER_INTERCEPT_SENDMMSG
3018static void read_msghdr_control(void *ctx, void *control, uptr controllen) {
3019 const unsigned kCmsgDataOffset =
3020 RoundUpTo(sizeof(__sanitizer_cmsghdr), sizeof(uptr));
3021
3022 char *p = (char *)control;
3023 char *const control_end = p + controllen;
3024 while (true) {
3025 if (p + sizeof(__sanitizer_cmsghdr) > control_end) break;
3026 __sanitizer_cmsghdr *cmsg = (__sanitizer_cmsghdr *)p;
3027 COMMON_INTERCEPTOR_READ_RANGE(ctx, &cmsg->cmsg_len, sizeof(cmsg->cmsg_len));
3028
3029 if (p + RoundUpTo(cmsg->cmsg_len, sizeof(uptr)) > control_end) break;
3030
3031 COMMON_INTERCEPTOR_READ_RANGE(ctx, &cmsg->cmsg_level,
3032 sizeof(cmsg->cmsg_level));
3033 COMMON_INTERCEPTOR_READ_RANGE(ctx, &cmsg->cmsg_type,
3034 sizeof(cmsg->cmsg_type));
3035
3036 if (cmsg->cmsg_len > kCmsgDataOffset) {
3037 char *data = p + kCmsgDataOffset;
3038 unsigned data_len = cmsg->cmsg_len - kCmsgDataOffset;
3039 if (data_len > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, data, data_len);
3040 }
3041
3042 p += RoundUpTo(cmsg->cmsg_len, sizeof(uptr));
3043 }
3044}
3045
3046static void read_msghdr(void *ctx, struct __sanitizer_msghdr *msg,
3047 SSIZE_T maxlen) {
3048#define R(f) \
3049 COMMON_INTERCEPTOR_READ_RANGE(ctx, &msg->msg_##f, sizeof(msg->msg_##f))
3050 R(name);
3051 R(namelen);
3052 R(iov);
3053 R(iovlen);
3054 R(control);
3055 R(controllen);
3056 R(flags);
3057#undef R
3058 if (msg->msg_name && msg->msg_namelen)
3059 COMMON_INTERCEPTOR_READ_RANGE(ctx, msg->msg_name, msg->msg_namelen);
3060 if (msg->msg_iov && msg->msg_iovlen)
3061 COMMON_INTERCEPTOR_READ_RANGE(ctx, msg->msg_iov,
3062 sizeof(*msg->msg_iov) * msg->msg_iovlen);
3063 read_iovec(ctx, msg->msg_iov, msg->msg_iovlen, maxlen);
3064 if (msg->msg_control && msg->msg_controllen)
3065 read_msghdr_control(ctx, msg->msg_control, msg->msg_controllen);
3066}
3067#endif
3068
3069#if SANITIZER_INTERCEPT_SENDMSG
3070INTERCEPTOR(SSIZE_T, sendmsg, int fd, struct __sanitizer_msghdr *msg,
3071 int flags) {
3072 void *ctx;
3073 COMMON_INTERCEPTOR_ENTER(ctx, sendmsg, fd, msg, flags);
3074 if (fd >= 0) {
3075 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
3076 COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
3077 }
3078 SSIZE_T res = REAL(sendmsg)(fd, msg, flags);
3079 if (common_flags()->intercept_send && res >= 0 && msg)
3080 read_msghdr(ctx, msg, res);
3081 return res;
3082}
3083#define INIT_SENDMSG COMMON_INTERCEPT_FUNCTION(sendmsg);
3084#else
3085#define INIT_SENDMSG
3086#endif
3087
3088#if SANITIZER_INTERCEPT_SENDMMSG
3089INTERCEPTOR(int, sendmmsg, int fd, struct __sanitizer_mmsghdr *msgvec,
3090 unsigned vlen, int flags) {
3091 void *ctx;
3092 COMMON_INTERCEPTOR_ENTER(ctx, sendmmsg, fd, msgvec, vlen, flags);
3093 if (fd >= 0) {
3094 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
3095 COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
3096 }
3097 int res = REAL(sendmmsg)(fd, msgvec, vlen, flags);
3098 if (res >= 0 && msgvec) {
3099 for (int i = 0; i < res; ++i) {
3100 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &msgvec[i].msg_len,
3101 sizeof(msgvec[i].msg_len));
3102 if (common_flags()->intercept_send)
3103 read_msghdr(ctx, &msgvec[i].msg_hdr, msgvec[i].msg_len);
3104 }
3105 }
3106 return res;
3107}
3108#define INIT_SENDMMSG COMMON_INTERCEPT_FUNCTION(sendmmsg);
3109#else
3110#define INIT_SENDMMSG
3111#endif
3112
3113#if SANITIZER_INTERCEPT_SYSMSG
3114INTERCEPTOR(int, msgsnd, int msqid, const void *msgp, SIZE_T msgsz,
3115 int msgflg) {
3116 void *ctx;
3117 COMMON_INTERCEPTOR_ENTER(ctx, msgsnd, msqid, msgp, msgsz, msgflg);
3118 if (msgp)
3119 COMMON_INTERCEPTOR_READ_RANGE(ctx, msgp, sizeof(long) + msgsz);
3120 int res = REAL(msgsnd)(msqid, msgp, msgsz, msgflg);
3121 return res;
3122}
3123
3124INTERCEPTOR(SSIZE_T, msgrcv, int msqid, void *msgp, SIZE_T msgsz,
3125 long msgtyp, int msgflg) {
3126 void *ctx;
3127 COMMON_INTERCEPTOR_ENTER(ctx, msgrcv, msqid, msgp, msgsz, msgtyp, msgflg);
3128 SSIZE_T len = REAL(msgrcv)(msqid, msgp, msgsz, msgtyp, msgflg);
3129 if (len != -1)
3130 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msgp, sizeof(long) + len);
3131 return len;
3132}
3133
3134#define INIT_SYSMSG \
3135 COMMON_INTERCEPT_FUNCTION(msgsnd); \
3136 COMMON_INTERCEPT_FUNCTION(msgrcv);
3137#else
3138#define INIT_SYSMSG
3139#endif
3140
3141#if SANITIZER_INTERCEPT_GETPEERNAME
3142INTERCEPTOR(int, getpeername, int sockfd, void *addr, unsigned *addrlen) {
3143 void *ctx;
3144 COMMON_INTERCEPTOR_ENTER(ctx, getpeername, sockfd, addr, addrlen);
3145 unsigned addr_sz;
3146 if (addrlen) addr_sz = *addrlen;
3147 // FIXME: under ASan the call below may write to freed memory and corrupt
3148 // its metadata. See
3149 // https://github.com/google/sanitizers/issues/321.
3150 int res = REAL(getpeername)(sockfd, addr, addrlen);
3151 if (!res && addr && addrlen)
3152 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addr_sz, *addrlen));
3153 return res;
3154}
3155#define INIT_GETPEERNAME COMMON_INTERCEPT_FUNCTION(getpeername);
3156#else
3157#define INIT_GETPEERNAME
3158#endif
3159
3160#if SANITIZER_INTERCEPT_SYSINFO
3161INTERCEPTOR(int, sysinfo, void *info) {
3162 void *ctx;
3163 // FIXME: under ASan the call below may write to freed memory and corrupt
3164 // its metadata. See
3165 // https://github.com/google/sanitizers/issues/321.
3166 COMMON_INTERCEPTOR_ENTER(ctx, sysinfo, info);
3167 int res = REAL(sysinfo)(info);
3168 if (!res && info)
3169 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, struct_sysinfo_sz);
3170 return res;
3171}
3172#define INIT_SYSINFO COMMON_INTERCEPT_FUNCTION(sysinfo);
3173#else
3174#define INIT_SYSINFO
3175#endif
3176
3177#if SANITIZER_INTERCEPT_READDIR
3178INTERCEPTOR(__sanitizer_dirent *, opendir, const char *path) {
3179 void *ctx;
3180 COMMON_INTERCEPTOR_ENTER(ctx, opendir, path);
3181 COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
3182 __sanitizer_dirent *res = REAL(opendir)(path);
3183 if (res)
3184 COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path);
3185 return res;
3186}
3187
3188INTERCEPTOR(__sanitizer_dirent *, readdir, void *dirp) {
3189 void *ctx;
3190 COMMON_INTERCEPTOR_ENTER(ctx, readdir, dirp);
3191 // FIXME: under ASan the call below may write to freed memory and corrupt
3192 // its metadata. See
3193 // https://github.com/google/sanitizers/issues/321.
3194 __sanitizer_dirent *res = REAL(readdir)(dirp);
3195 if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen);
3196 return res;
3197}
3198
3199INTERCEPTOR(int, readdir_r, void *dirp, __sanitizer_dirent *entry,
3200 __sanitizer_dirent **result) {
3201 void *ctx;
3202 COMMON_INTERCEPTOR_ENTER(ctx, readdir_r, dirp, entry, result);
3203 // FIXME: under ASan the call below may write to freed memory and corrupt
3204 // its metadata. See
3205 // https://github.com/google/sanitizers/issues/321.
3206 int res = REAL(readdir_r)(dirp, entry, result);
3207 if (!res) {
3208 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
3209 if (*result)
3210 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, (*result)->d_reclen);
3211 }
3212 return res;
3213}
3214
3215#define INIT_READDIR \
3216 COMMON_INTERCEPT_FUNCTION(opendir); \
3217 COMMON_INTERCEPT_FUNCTION(readdir); \
3218 COMMON_INTERCEPT_FUNCTION(readdir_r);
3219#else
3220#define INIT_READDIR
3221#endif
3222
3223#if SANITIZER_INTERCEPT_READDIR64
3224INTERCEPTOR(__sanitizer_dirent64 *, readdir64, void *dirp) {
3225 void *ctx;
3226 COMMON_INTERCEPTOR_ENTER(ctx, readdir64, dirp);
3227 // FIXME: under ASan the call below may write to freed memory and corrupt
3228 // its metadata. See
3229 // https://github.com/google/sanitizers/issues/321.
3230 __sanitizer_dirent64 *res = REAL(readdir64)(dirp);
3231 if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen);
3232 return res;
3233}
3234
3235INTERCEPTOR(int, readdir64_r, void *dirp, __sanitizer_dirent64 *entry,
3236 __sanitizer_dirent64 **result) {
3237 void *ctx;
3238 COMMON_INTERCEPTOR_ENTER(ctx, readdir64_r, dirp, entry, result);
3239 // FIXME: under ASan the call below may write to freed memory and corrupt
3240 // its metadata. See
3241 // https://github.com/google/sanitizers/issues/321.
3242 int res = REAL(readdir64_r)(dirp, entry, result);
3243 if (!res) {
3244 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
3245 if (*result)
3246 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, (*result)->d_reclen);
3247 }
3248 return res;
3249}
3250#define INIT_READDIR64 \
3251 COMMON_INTERCEPT_FUNCTION(readdir64); \
3252 COMMON_INTERCEPT_FUNCTION(readdir64_r);
3253#else
3254#define INIT_READDIR64
3255#endif
3256
3257#if SANITIZER_INTERCEPT_PTRACE
3258INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) {
3259 void *ctx;
3260 COMMON_INTERCEPTOR_ENTER(ctx, ptrace, request, pid, addr, data);
3261 __sanitizer_iovec local_iovec;
3262
3263 if (data) {
3264 if (request == ptrace_setregs) {
3265 COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_regs_struct_sz);
3266 } else if (request == ptrace_setfpregs) {
3267 COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpregs_struct_sz);
3268 } else if (request == ptrace_setfpxregs) {
3269 COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
3270 } else if (request == ptrace_setvfpregs) {
3271 COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_vfpregs_struct_sz);
3272 } else if (request == ptrace_setsiginfo) {
3273 COMMON_INTERCEPTOR_READ_RANGE(ctx, data, siginfo_t_sz);
3274
3275 // Some kernel might zero the iovec::iov_base in case of invalid
3276 // write access. In this case copy the invalid address for further
3277 // inspection.
3278 } else if (request == ptrace_setregset || request == ptrace_getregset) {
3279 __sanitizer_iovec *iovec = (__sanitizer_iovec*)data;
3280 COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec, sizeof(*iovec));
3281 local_iovec = *iovec;
3282 if (request == ptrace_setregset)
3283 COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec->iov_base, iovec->iov_len);
3284 }
3285 }
3286
3287 // FIXME: under ASan the call below may write to freed memory and corrupt
3288 // its metadata. See
3289 // https://github.com/google/sanitizers/issues/321.
3290 uptr res = REAL(ptrace)(request, pid, addr, data);
3291
3292 if (!res && data) {
3293 // Note that PEEK* requests assign different meaning to the return value.
3294 // This function does not handle them (nor does it need to).
3295 if (request == ptrace_getregs) {
3296 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_regs_struct_sz);
3297 } else if (request == ptrace_getfpregs) {
3298 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpregs_struct_sz);
3299 } else if (request == ptrace_getfpxregs) {
3300 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
3301 } else if (request == ptrace_getvfpregs) {
3302 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_vfpregs_struct_sz);
3303 } else if (request == ptrace_getsiginfo) {
3304 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, siginfo_t_sz);
3305 } else if (request == ptrace_geteventmsg) {
3306 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, sizeof(unsigned long));
3307 } else if (request == ptrace_getregset) {
3308 __sanitizer_iovec *iovec = (__sanitizer_iovec*)data;
3309 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iovec, sizeof(*iovec));
3310 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, local_iovec.iov_base,
3311 local_iovec.iov_len);
3312 }
3313 }
3314 return res;
3315}
3316
3317#define INIT_PTRACE COMMON_INTERCEPT_FUNCTION(ptrace);
3318#else
3319#define INIT_PTRACE
3320#endif
3321
3322#if SANITIZER_INTERCEPT_SETLOCALE
3323static void unpoison_ctype_arrays(void *ctx) {
3324#if SANITIZER_NETBSD
3325 // These arrays contain 256 regular elements in unsigned char range + 1 EOF
3326 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, _ctype_tab_, 257 * sizeof(short));
3327 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, _toupper_tab_, 257 * sizeof(short));
3328 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, _tolower_tab_, 257 * sizeof(short));
3329#endif
3330}
3331
3332INTERCEPTOR(char *, setlocale, int category, char *locale) {
3333 void *ctx;
3334 COMMON_INTERCEPTOR_ENTER(ctx, setlocale, category, locale);
3335 if (locale)
3336 COMMON_INTERCEPTOR_READ_RANGE(ctx, locale, REAL(strlen)(locale) + 1);
3337 char *res = REAL(setlocale)(category, locale);
3338 if (res) {
3339 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
3340 unpoison_ctype_arrays(ctx);
3341 }
3342 return res;
3343}
3344
3345#define INIT_SETLOCALE COMMON_INTERCEPT_FUNCTION(setlocale);
3346#else
3347#define INIT_SETLOCALE
3348#endif
3349
3350#if SANITIZER_INTERCEPT_GETCWD
3351INTERCEPTOR(char *, getcwd, char *buf, SIZE_T size) {
3352 void *ctx;
3353 COMMON_INTERCEPTOR_ENTER(ctx, getcwd, buf, size);
3354 // FIXME: under ASan the call below may write to freed memory and corrupt
3355 // its metadata. See
3356 // https://github.com/google/sanitizers/issues/321.
3357 char *res = REAL(getcwd)(buf, size);
3358 if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
3359 return res;
3360}
3361#define INIT_GETCWD COMMON_INTERCEPT_FUNCTION(getcwd);
3362#else
3363#define INIT_GETCWD
3364#endif
3365
3366#if SANITIZER_INTERCEPT_GET_CURRENT_DIR_NAME
3367INTERCEPTOR(char *, get_current_dir_name, int fake) {
3368 void *ctx;
3369 COMMON_INTERCEPTOR_ENTER(ctx, get_current_dir_name, fake);
3370 // FIXME: under ASan the call below may write to freed memory and corrupt
3371 // its metadata. See
3372 // https://github.com/google/sanitizers/issues/321.
3373 char *res = REAL(get_current_dir_name)(fake);
3374 if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
3375 return res;
3376}
3377
3378#define INIT_GET_CURRENT_DIR_NAME \
3379 COMMON_INTERCEPT_FUNCTION(get_current_dir_name);
3380#else
3381#define INIT_GET_CURRENT_DIR_NAME
3382#endif
3383
3384UNUSED static inline void FixRealStrtolEndptr(const char *nptr, char **endptr) {
3385 CHECK(endptr);
3386 if (nptr == *endptr) {
3387 // No digits were found at strtol call, we need to find out the last
3388 // symbol accessed by strtoll on our own.
3389 // We get this symbol by skipping leading blanks and optional +/- sign.
3390 while (IsSpace(*nptr)) nptr++;
3391 if (*nptr == '+' || *nptr == '-') nptr++;
3392 *endptr = const_cast<char *>(nptr);
3393 }
3394 CHECK(*endptr >= nptr);
3395}
3396
3397UNUSED static inline void StrtolFixAndCheck(void *ctx, const char *nptr,
3398 char **endptr, char *real_endptr, int base) {
3399 if (endptr) {
3400 *endptr = real_endptr;
3401 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, endptr, sizeof(*endptr));
3402 }
3403 // If base has unsupported value, strtol can exit with EINVAL
3404 // without reading any characters. So do additional checks only
3405 // if base is valid.
3406 bool is_valid_base = (base == 0) || (2 <= base && base <= 36);
3407 if (is_valid_base) {
3408 FixRealStrtolEndptr(nptr, &real_endptr);
3409 }
3410 COMMON_INTERCEPTOR_READ_STRING(ctx, nptr, is_valid_base ?
3411 (real_endptr - nptr) + 1 : 0);
3412}
3413
3414
3415#if SANITIZER_INTERCEPT_STRTOIMAX
3416INTERCEPTOR(INTMAX_T, strtoimax, const char *nptr, char **endptr, int base) {
3417 void *ctx;
3418 COMMON_INTERCEPTOR_ENTER(ctx, strtoimax, nptr, endptr, base);
3419 // FIXME: under ASan the call below may write to freed memory and corrupt
3420 // its metadata. See
3421 // https://github.com/google/sanitizers/issues/321.
3422 char *real_endptr;
3423 INTMAX_T res = REAL(strtoimax)(nptr, &real_endptr, base);
3424 StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
3425 return res;
3426}
3427
3428INTERCEPTOR(UINTMAX_T, strtoumax, const char *nptr, char **endptr, int base) {
3429 void *ctx;
3430 COMMON_INTERCEPTOR_ENTER(ctx, strtoumax, nptr, endptr, base);
3431 // FIXME: under ASan the call below may write to freed memory and corrupt
3432 // its metadata. See
3433 // https://github.com/google/sanitizers/issues/321.
3434 char *real_endptr;
3435 UINTMAX_T res = REAL(strtoumax)(nptr, &real_endptr, base);
3436 StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
3437 return res;
3438}
3439
3440#define INIT_STRTOIMAX \
3441 COMMON_INTERCEPT_FUNCTION(strtoimax); \
3442 COMMON_INTERCEPT_FUNCTION(strtoumax);
3443#else
3444#define INIT_STRTOIMAX
3445#endif
3446
3447#if SANITIZER_INTERCEPT_MBSTOWCS
3448INTERCEPTOR(SIZE_T, mbstowcs, wchar_t *dest, const char *src, SIZE_T len) {
3449 void *ctx;
3450 COMMON_INTERCEPTOR_ENTER(ctx, mbstowcs, dest, src, len);
3451 // FIXME: under ASan the call below may write to freed memory and corrupt
3452 // its metadata. See
3453 // https://github.com/google/sanitizers/issues/321.
3454 SIZE_T res = REAL(mbstowcs)(dest, src, len);
3455 if (res != (SIZE_T) - 1 && dest) {
3456 SIZE_T write_cnt = res + (res < len);
3457 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
3458 }
3459 return res;
3460}
3461
3462INTERCEPTOR(SIZE_T, mbsrtowcs, wchar_t *dest, const char **src, SIZE_T len,
3463 void *ps) {
3464 void *ctx;
3465 COMMON_INTERCEPTOR_ENTER(ctx, mbsrtowcs, dest, src, len, ps);
3466 if (src) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
3467 if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
3468 // FIXME: under ASan the call below may write to freed memory and corrupt
3469 // its metadata. See
3470 // https://github.com/google/sanitizers/issues/321.
3471 SIZE_T res = REAL(mbsrtowcs)(dest, src, len, ps);
3472 if (res != (SIZE_T)(-1) && dest && src) {
3473 // This function, and several others, may or may not write the terminating
3474 // \0 character. They write it iff they clear *src.
3475 SIZE_T write_cnt = res + !*src;
3476 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
3477 }
3478 return res;
3479}
3480
3481#define INIT_MBSTOWCS \
3482 COMMON_INTERCEPT_FUNCTION(mbstowcs); \
3483 COMMON_INTERCEPT_FUNCTION(mbsrtowcs);
3484#else
3485#define INIT_MBSTOWCS
3486#endif
3487
3488#if SANITIZER_INTERCEPT_MBSNRTOWCS
3489INTERCEPTOR(SIZE_T, mbsnrtowcs, wchar_t *dest, const char **src, SIZE_T nms,
3490 SIZE_T len, void *ps) {
3491 void *ctx;
3492 COMMON_INTERCEPTOR_ENTER(ctx, mbsnrtowcs, dest, src, nms, len, ps);
3493 if (src) {
3494 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
3495 if (nms) COMMON_INTERCEPTOR_READ_RANGE(ctx, *src, nms);
3496 }
3497 if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
3498 // FIXME: under ASan the call below may write to freed memory and corrupt
3499 // its metadata. See
3500 // https://github.com/google/sanitizers/issues/321.
3501 SIZE_T res = REAL(mbsnrtowcs)(dest, src, nms, len, ps);
3502 if (res != (SIZE_T)(-1) && dest && src) {
3503 SIZE_T write_cnt = res + !*src;
3504 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
3505 }
3506 return res;
3507}
3508
3509#define INIT_MBSNRTOWCS COMMON_INTERCEPT_FUNCTION(mbsnrtowcs);
3510#else
3511#define INIT_MBSNRTOWCS
3512#endif
3513
3514#if SANITIZER_INTERCEPT_WCSTOMBS
3515INTERCEPTOR(SIZE_T, wcstombs, char *dest, const wchar_t *src, SIZE_T len) {
3516 void *ctx;
3517 COMMON_INTERCEPTOR_ENTER(ctx, wcstombs, dest, src, len);
3518 // FIXME: under ASan the call below may write to freed memory and corrupt
3519 // its metadata. See
3520 // https://github.com/google/sanitizers/issues/321.
3521 SIZE_T res = REAL(wcstombs)(dest, src, len);
3522 if (res != (SIZE_T) - 1 && dest) {
3523 SIZE_T write_cnt = res + (res < len);
3524 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
3525 }
3526 return res;
3527}
3528
3529INTERCEPTOR(SIZE_T, wcsrtombs, char *dest, const wchar_t **src, SIZE_T len,
3530 void *ps) {
3531 void *ctx;
3532 COMMON_INTERCEPTOR_ENTER(ctx, wcsrtombs, dest, src, len, ps);
3533 if (src) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
3534 if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
3535 // FIXME: under ASan the call below may write to freed memory and corrupt
3536 // its metadata. See
3537 // https://github.com/google/sanitizers/issues/321.
3538 SIZE_T res = REAL(wcsrtombs)(dest, src, len, ps);
3539 if (res != (SIZE_T) - 1 && dest && src) {
3540 SIZE_T write_cnt = res + !*src;
3541 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
3542 }
3543 return res;
3544}
3545
3546#define INIT_WCSTOMBS \
3547 COMMON_INTERCEPT_FUNCTION(wcstombs); \
3548 COMMON_INTERCEPT_FUNCTION(wcsrtombs);
3549#else
3550#define INIT_WCSTOMBS
3551#endif
3552
3553#if SANITIZER_INTERCEPT_WCSNRTOMBS
3554INTERCEPTOR(SIZE_T, wcsnrtombs, char *dest, const wchar_t **src, SIZE_T nms,
3555 SIZE_T len, void *ps) {
3556 void *ctx;
3557 COMMON_INTERCEPTOR_ENTER(ctx, wcsnrtombs, dest, src, nms, len, ps);
3558 if (src) {
3559 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
3560 if (nms) COMMON_INTERCEPTOR_READ_RANGE(ctx, *src, nms);
3561 }
3562 if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
3563 // FIXME: under ASan the call below may write to freed memory and corrupt
3564 // its metadata. See
3565 // https://github.com/google/sanitizers/issues/321.
3566 SIZE_T res = REAL(wcsnrtombs)(dest, src, nms, len, ps);
3567 if (res != ((SIZE_T)-1) && dest && src) {
3568 SIZE_T write_cnt = res + !*src;
3569 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
3570 }
3571 return res;
3572}
3573
3574#define INIT_WCSNRTOMBS COMMON_INTERCEPT_FUNCTION(wcsnrtombs);
3575#else
3576#define INIT_WCSNRTOMBS
3577#endif
3578
3579
3580#if SANITIZER_INTERCEPT_WCRTOMB
3581INTERCEPTOR(SIZE_T, wcrtomb, char *dest, wchar_t src, void *ps) {
3582 void *ctx;
3583 COMMON_INTERCEPTOR_ENTER(ctx, wcrtomb, dest, src, ps);
3584 if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
3585
3586 if (!dest)
3587 return REAL(wcrtomb)(dest, src, ps);
3588
3589 char local_dest[32];
3590 SIZE_T res = REAL(wcrtomb)(local_dest, src, ps);
3591 if (res != ((SIZE_T)-1)) {
3592 CHECK_LE(res, sizeof(local_dest));
3593 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, res);
3594 REAL(memcpy)(dest, local_dest, res);
3595 }
3596 return res;
3597}
3598
3599#define INIT_WCRTOMB COMMON_INTERCEPT_FUNCTION(wcrtomb);
3600#else
3601#define INIT_WCRTOMB
3602#endif
3603
3604#if SANITIZER_INTERCEPT_WCTOMB
3605INTERCEPTOR(int, wctomb, char *dest, wchar_t src) {
3606 void *ctx;
3607 COMMON_INTERCEPTOR_ENTER(ctx, wctomb, dest, src);
3608 if (!dest)
3609 return REAL(wctomb)(dest, src);
3610
3611 char local_dest[32];
3612 int res = REAL(wctomb)(local_dest, src);
3613 if (res != -1) {
3614 CHECK_LE(res, sizeof(local_dest));
3615 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, res);
3616 REAL(memcpy)(dest, local_dest, res);
3617 }
3618 return res;
3619}
3620
3621#define INIT_WCTOMB COMMON_INTERCEPT_FUNCTION(wctomb);
3622#else
3623#define INIT_WCTOMB
3624#endif
3625
3626#if SANITIZER_INTERCEPT_TCGETATTR
3627INTERCEPTOR(int, tcgetattr, int fd, void *termios_p) {
3628 void *ctx;
3629 COMMON_INTERCEPTOR_ENTER(ctx, tcgetattr, fd, termios_p);
3630 // FIXME: under ASan the call below may write to freed memory and corrupt
3631 // its metadata. See
3632 // https://github.com/google/sanitizers/issues/321.
3633 int res = REAL(tcgetattr)(fd, termios_p);
3634 if (!res && termios_p)
3635 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, termios_p, struct_termios_sz);
3636 return res;
3637}
3638
3639#define INIT_TCGETATTR COMMON_INTERCEPT_FUNCTION(tcgetattr);
3640#else
3641#define INIT_TCGETATTR
3642#endif
3643
3644#if SANITIZER_INTERCEPT_REALPATH
3645INTERCEPTOR(char *, realpath, const char *path, char *resolved_path) {
3646 void *ctx;
3647 COMMON_INTERCEPTOR_ENTER(ctx, realpath, path, resolved_path);
3648 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
3649
3650 // Workaround a bug in glibc where dlsym(RTLD_NEXT, ...) returns the oldest
3651 // version of a versioned symbol. For realpath(), this gives us something
3652 // (called __old_realpath) that does not handle NULL in the second argument.
3653 // Handle it as part of the interceptor.
3654 char *allocated_path = nullptr;
3655 if (!resolved_path)
3656 allocated_path = resolved_path = (char *)WRAP(malloc)(path_max + 1);
3657
3658 char *res = REAL(realpath)(path, resolved_path);
3659 if (allocated_path && !res) WRAP(free)(allocated_path);
3660 if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
3661 return res;
3662}
3663#define INIT_REALPATH COMMON_INTERCEPT_FUNCTION(realpath);
3664#else
3665#define INIT_REALPATH
3666#endif
3667
3668#if SANITIZER_INTERCEPT_CANONICALIZE_FILE_NAME
3669INTERCEPTOR(char *, canonicalize_file_name, const char *path) {
3670 void *ctx;
3671 COMMON_INTERCEPTOR_ENTER(ctx, canonicalize_file_name, path);
3672 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
3673 char *res = REAL(canonicalize_file_name)(path);
3674 if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
3675 return res;
3676}
3677#define INIT_CANONICALIZE_FILE_NAME \
3678 COMMON_INTERCEPT_FUNCTION(canonicalize_file_name);
3679#else
3680#define INIT_CANONICALIZE_FILE_NAME
3681#endif
3682
3683#if SANITIZER_INTERCEPT_CONFSTR
3684INTERCEPTOR(SIZE_T, confstr, int name, char *buf, SIZE_T len) {
3685 void *ctx;
3686 COMMON_INTERCEPTOR_ENTER(ctx, confstr, name, buf, len);
3687 // FIXME: under ASan the call below may write to freed memory and corrupt
3688 // its metadata. See
3689 // https://github.com/google/sanitizers/issues/321.
3690 SIZE_T res = REAL(confstr)(name, buf, len);
3691 if (buf && res)
3692 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, res < len ? res : len);
3693 return res;
3694}
3695#define INIT_CONFSTR COMMON_INTERCEPT_FUNCTION(confstr);
3696#else
3697#define INIT_CONFSTR
3698#endif
3699
3700#if SANITIZER_INTERCEPT_SCHED_GETAFFINITY
3701INTERCEPTOR(int, sched_getaffinity, int pid, SIZE_T cpusetsize, void *mask) {
3702 void *ctx;
3703 COMMON_INTERCEPTOR_ENTER(ctx, sched_getaffinity, pid, cpusetsize, mask);
3704 // FIXME: under ASan the call below may write to freed memory and corrupt
3705 // its metadata. See
3706 // https://github.com/google/sanitizers/issues/321.
3707 int res = REAL(sched_getaffinity)(pid, cpusetsize, mask);
3708 if (mask && !res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mask, cpusetsize);
3709 return res;
3710}
3711#define INIT_SCHED_GETAFFINITY COMMON_INTERCEPT_FUNCTION(sched_getaffinity);
3712#else
3713#define INIT_SCHED_GETAFFINITY
3714#endif
3715
3716#if SANITIZER_INTERCEPT_SCHED_GETPARAM
3717INTERCEPTOR(int, sched_getparam, int pid, void *param) {
3718 void *ctx;
3719 COMMON_INTERCEPTOR_ENTER(ctx, sched_getparam, pid, param);
3720 int res = REAL(sched_getparam)(pid, param);
3721 if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, param, struct_sched_param_sz);
3722 return res;
3723}
3724#define INIT_SCHED_GETPARAM COMMON_INTERCEPT_FUNCTION(sched_getparam);
3725#else
3726#define INIT_SCHED_GETPARAM
3727#endif
3728
3729#if SANITIZER_INTERCEPT_STRERROR
3730INTERCEPTOR(char *, strerror, int errnum) {
3731 void *ctx;
3732 COMMON_INTERCEPTOR_ENTER(ctx, strerror, errnum);
3733 COMMON_INTERCEPTOR_STRERROR();
3734 char *res = REAL(strerror)(errnum);
3735 if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
3736 return res;
3737}
3738#define INIT_STRERROR COMMON_INTERCEPT_FUNCTION(strerror);
3739#else
3740#define INIT_STRERROR
3741#endif
3742
3743#if SANITIZER_INTERCEPT_STRERROR_R
3744// There are 2 versions of strerror_r:
3745// * POSIX version returns 0 on success, negative error code on failure,
3746// writes message to buf.
3747// * GNU version returns message pointer, which points to either buf or some
3748// static storage.
3749#if ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE) || \
3750 SANITIZER_MAC || SANITIZER_ANDROID || SANITIZER_NETBSD || \
3751 SANITIZER_FREEBSD || SANITIZER_OPENBSD
3752// POSIX version. Spec is not clear on whether buf is NULL-terminated.
3753// At least on OSX, buf contents are valid even when the call fails.
3754INTERCEPTOR(int, strerror_r, int errnum, char *buf, SIZE_T buflen) {
3755 void *ctx;
3756 COMMON_INTERCEPTOR_ENTER(ctx, strerror_r, errnum, buf, buflen);
3757 // FIXME: under ASan the call below may write to freed memory and corrupt
3758 // its metadata. See
3759 // https://github.com/google/sanitizers/issues/321.
3760 int res = REAL(strerror_r)(errnum, buf, buflen);
3761
3762 SIZE_T sz = internal_strnlen(buf, buflen);
3763 if (sz < buflen) ++sz;
3764 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sz);
3765 return res;
3766}
3767#else
3768// GNU version.
3769INTERCEPTOR(char *, strerror_r, int errnum, char *buf, SIZE_T buflen) {
3770 void *ctx;
3771 COMMON_INTERCEPTOR_ENTER(ctx, strerror_r, errnum, buf, buflen);
3772 // FIXME: under ASan the call below may write to freed memory and corrupt
3773 // its metadata. See
3774 // https://github.com/google/sanitizers/issues/321.
3775 char *res = REAL(strerror_r)(errnum, buf, buflen);
3776 if (res == buf)
3777 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
3778 else
3779 COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
3780 return res;
3781}
3782#endif //(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE ||
3783 //SANITIZER_MAC
3784#define INIT_STRERROR_R COMMON_INTERCEPT_FUNCTION(strerror_r);
3785#else
3786#define INIT_STRERROR_R
3787#endif
3788
3789#if SANITIZER_INTERCEPT_XPG_STRERROR_R
3790INTERCEPTOR(int, __xpg_strerror_r, int errnum, char *buf, SIZE_T buflen) {
3791 void *ctx;
3792 COMMON_INTERCEPTOR_ENTER(ctx, __xpg_strerror_r, errnum, buf, buflen);
3793 // FIXME: under ASan the call below may write to freed memory and corrupt
3794 // its metadata. See
3795 // https://github.com/google/sanitizers/issues/321.
3796 int res = REAL(__xpg_strerror_r)(errnum, buf, buflen);
3797 // This version always returns a null-terminated string.
3798 if (buf && buflen)
3799 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
3800 return res;
3801}
3802#define INIT_XPG_STRERROR_R COMMON_INTERCEPT_FUNCTION(__xpg_strerror_r);
3803#else
3804#define INIT_XPG_STRERROR_R
3805#endif
3806
3807#if SANITIZER_INTERCEPT_SCANDIR
3808typedef int (*scandir_filter_f)(const struct __sanitizer_dirent *);
3809typedef int (*scandir_compar_f)(const struct __sanitizer_dirent **,
3810 const struct __sanitizer_dirent **);
3811
3812static THREADLOCAL scandir_filter_f scandir_filter;
3813static THREADLOCAL scandir_compar_f scandir_compar;
3814
3815static int wrapped_scandir_filter(const struct __sanitizer_dirent *dir) {
3816 COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
3817 COMMON_INTERCEPTOR_INITIALIZE_RANGE(dir, dir->d_reclen);
3818 return scandir_filter(dir);
3819}
3820
3821static int wrapped_scandir_compar(const struct __sanitizer_dirent **a,
3822 const struct __sanitizer_dirent **b) {
3823 COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
3824 COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, sizeof(*a));
3825 COMMON_INTERCEPTOR_INITIALIZE_RANGE(*a, (*a)->d_reclen);
3826 COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, sizeof(*b));
3827 COMMON_INTERCEPTOR_INITIALIZE_RANGE(*b, (*b)->d_reclen);
3828 return scandir_compar(a, b);
3829}
3830
3831INTERCEPTOR(int, scandir, char *dirp, __sanitizer_dirent ***namelist,
3832 scandir_filter_f filter, scandir_compar_f compar) {
3833 void *ctx;
3834 COMMON_INTERCEPTOR_ENTER(ctx, scandir, dirp, namelist, filter, compar);
3835 if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, REAL(strlen)(dirp) + 1);
3836 scandir_filter = filter;
3837 scandir_compar = compar;
3838 // FIXME: under ASan the call below may write to freed memory and corrupt
3839 // its metadata. See
3840 // https://github.com/google/sanitizers/issues/321.
3841 int res = REAL(scandir)(dirp, namelist,
3842 filter ? wrapped_scandir_filter : nullptr,
3843 compar ? wrapped_scandir_compar : nullptr);
3844 scandir_filter = nullptr;
3845 scandir_compar = nullptr;
3846 if (namelist && res > 0) {
3847 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelist, sizeof(*namelist));
3848 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *namelist, sizeof(**namelist) * res);
3849 for (int i = 0; i < res; ++i)
3850 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (*namelist)[i],
3851 (*namelist)[i]->d_reclen);
3852 }
3853 return res;
3854}
3855#define INIT_SCANDIR COMMON_INTERCEPT_FUNCTION(scandir);
3856#else
3857#define INIT_SCANDIR
3858#endif
3859
3860#if SANITIZER_INTERCEPT_SCANDIR64
3861typedef int (*scandir64_filter_f)(const struct __sanitizer_dirent64 *);
3862typedef int (*scandir64_compar_f)(const struct __sanitizer_dirent64 **,
3863 const struct __sanitizer_dirent64 **);
3864
3865static THREADLOCAL scandir64_filter_f scandir64_filter;
3866static THREADLOCAL scandir64_compar_f scandir64_compar;
3867
3868static int wrapped_scandir64_filter(const struct __sanitizer_dirent64 *dir) {
3869 COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
3870 COMMON_INTERCEPTOR_INITIALIZE_RANGE(dir, dir->d_reclen);
3871 return scandir64_filter(dir);
3872}
3873
3874static int wrapped_scandir64_compar(const struct __sanitizer_dirent64 **a,
3875 const struct __sanitizer_dirent64 **b) {
3876 COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
3877 COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, sizeof(*a));
3878 COMMON_INTERCEPTOR_INITIALIZE_RANGE(*a, (*a)->d_reclen);
3879 COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, sizeof(*b));
3880 COMMON_INTERCEPTOR_INITIALIZE_RANGE(*b, (*b)->d_reclen);
3881 return scandir64_compar(a, b);
3882}
3883
3884INTERCEPTOR(int, scandir64, char *dirp, __sanitizer_dirent64 ***namelist,
3885 scandir64_filter_f filter, scandir64_compar_f compar) {
3886 void *ctx;
3887 COMMON_INTERCEPTOR_ENTER(ctx, scandir64, dirp, namelist, filter, compar);
3888 if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, REAL(strlen)(dirp) + 1);
3889 scandir64_filter = filter;
3890 scandir64_compar = compar;
3891 // FIXME: under ASan the call below may write to freed memory and corrupt
3892 // its metadata. See
3893 // https://github.com/google/sanitizers/issues/321.
3894 int res =
3895 REAL(scandir64)(dirp, namelist,
3896 filter ? wrapped_scandir64_filter : nullptr,
3897 compar ? wrapped_scandir64_compar : nullptr);
3898 scandir64_filter = nullptr;
3899 scandir64_compar = nullptr;
3900 if (namelist && res > 0) {
3901 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelist, sizeof(*namelist));
3902 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *namelist, sizeof(**namelist) * res);
3903 for (int i = 0; i < res; ++i)
3904 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (*namelist)[i],
3905 (*namelist)[i]->d_reclen);
3906 }
3907 return res;
3908}
3909#define INIT_SCANDIR64 COMMON_INTERCEPT_FUNCTION(scandir64);
3910#else
3911#define INIT_SCANDIR64
3912#endif
3913
3914#if SANITIZER_INTERCEPT_GETGROUPS
3915INTERCEPTOR(int, getgroups, int size, u32 *lst) {
3916 void *ctx;
3917 COMMON_INTERCEPTOR_ENTER(ctx, getgroups, size, lst);
3918 // FIXME: under ASan the call below may write to freed memory and corrupt
3919 // its metadata. See
3920 // https://github.com/google/sanitizers/issues/321.
3921 int res = REAL(getgroups)(size, lst);
3922 if (res >= 0 && lst && size > 0)
3923 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lst, res * sizeof(*lst));
3924 return res;
3925}
3926#define INIT_GETGROUPS COMMON_INTERCEPT_FUNCTION(getgroups);
3927#else
3928#define INIT_GETGROUPS
3929#endif
3930
3931#if SANITIZER_INTERCEPT_POLL
3932static void read_pollfd(void *ctx, __sanitizer_pollfd *fds,
3933 __sanitizer_nfds_t nfds) {
3934 for (unsigned i = 0; i < nfds; ++i) {
3935 COMMON_INTERCEPTOR_READ_RANGE(ctx, &fds[i].fd, sizeof(fds[i].fd));
3936 COMMON_INTERCEPTOR_READ_RANGE(ctx, &fds[i].events, sizeof(fds[i].events));
3937 }
3938}
3939
3940static void write_pollfd(void *ctx, __sanitizer_pollfd *fds,
3941 __sanitizer_nfds_t nfds) {
3942 for (unsigned i = 0; i < nfds; ++i)
3943 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &fds[i].revents,
3944 sizeof(fds[i].revents));
3945}
3946
3947INTERCEPTOR(int, poll, __sanitizer_pollfd *fds, __sanitizer_nfds_t nfds,
3948 int timeout) {
3949 void *ctx;
3950 COMMON_INTERCEPTOR_ENTER(ctx, poll, fds, nfds, timeout);
3951 if (fds && nfds) read_pollfd(ctx, fds, nfds);
3952 int res = COMMON_INTERCEPTOR_BLOCK_REAL(poll)(fds, nfds, timeout);
3953 if (fds && nfds) write_pollfd(ctx, fds, nfds);
3954 return res;
3955}
3956#define INIT_POLL COMMON_INTERCEPT_FUNCTION(poll);
3957#else
3958#define INIT_POLL
3959#endif
3960
3961#if SANITIZER_INTERCEPT_PPOLL
3962INTERCEPTOR(int, ppoll, __sanitizer_pollfd *fds, __sanitizer_nfds_t nfds,
3963 void *timeout_ts, __sanitizer_sigset_t *sigmask) {
3964 void *ctx;
3965 COMMON_INTERCEPTOR_ENTER(ctx, ppoll, fds, nfds, timeout_ts, sigmask);
3966 if (fds && nfds) read_pollfd(ctx, fds, nfds);
3967 if (timeout_ts)
3968 COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout_ts, struct_timespec_sz);
3969 if (sigmask) COMMON_INTERCEPTOR_READ_RANGE(ctx, sigmask, sizeof(*sigmask));
3970 int res =
3971 COMMON_INTERCEPTOR_BLOCK_REAL(ppoll)(fds, nfds, timeout_ts, sigmask);
3972 if (fds && nfds) write_pollfd(ctx, fds, nfds);
3973 return res;
3974}
3975#define INIT_PPOLL COMMON_INTERCEPT_FUNCTION(ppoll);
3976#else
3977#define INIT_PPOLL
3978#endif
3979
3980#if SANITIZER_INTERCEPT_WORDEXP
3981INTERCEPTOR(int, wordexp, char *s, __sanitizer_wordexp_t *p, int flags) {
3982 void *ctx;
3983 COMMON_INTERCEPTOR_ENTER(ctx, wordexp, s, p, flags);
3984 if (s) COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
3985 // FIXME: under ASan the call below may write to freed memory and corrupt
3986 // its metadata. See
3987 // https://github.com/google/sanitizers/issues/321.
3988 int res = REAL(wordexp)(s, p, flags);
3989 if (!res && p) {
3990 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
3991 if (p->we_wordc)
3992 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->we_wordv,
3993 sizeof(*p->we_wordv) * p->we_wordc);
3994 for (uptr i = 0; i < p->we_wordc; ++i) {
3995 char *w = p->we_wordv[i];
3996 if (w) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, w, REAL(strlen)(w) + 1);
3997 }
3998 }
3999 return res;
4000}
4001#define INIT_WORDEXP COMMON_INTERCEPT_FUNCTION(wordexp);
4002#else
4003#define INIT_WORDEXP
4004#endif
4005
4006#if SANITIZER_INTERCEPT_SIGWAIT
4007INTERCEPTOR(int, sigwait, __sanitizer_sigset_t *set, int *sig) {
4008 void *ctx;
4009 COMMON_INTERCEPTOR_ENTER(ctx, sigwait, set, sig);
4010 if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
4011 // FIXME: under ASan the call below may write to freed memory and corrupt
4012 // its metadata. See
4013 // https://github.com/google/sanitizers/issues/321.
4014 int res = REAL(sigwait)(set, sig);
4015 if (!res && sig) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sig, sizeof(*sig));
4016 return res;
4017}
4018#define INIT_SIGWAIT COMMON_INTERCEPT_FUNCTION(sigwait);
4019#else
4020#define INIT_SIGWAIT
4021#endif
4022
4023#if SANITIZER_INTERCEPT_SIGWAITINFO
4024INTERCEPTOR(int, sigwaitinfo, __sanitizer_sigset_t *set, void *info) {
4025 void *ctx;
4026 COMMON_INTERCEPTOR_ENTER(ctx, sigwaitinfo, set, info);
4027 if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
4028 // FIXME: under ASan the call below may write to freed memory and corrupt
4029 // its metadata. See
4030 // https://github.com/google/sanitizers/issues/321.
4031 int res = REAL(sigwaitinfo)(set, info);
4032 if (res > 0 && info) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, siginfo_t_sz);
4033 return res;
4034}
4035#define INIT_SIGWAITINFO COMMON_INTERCEPT_FUNCTION(sigwaitinfo);
4036#else
4037#define INIT_SIGWAITINFO
4038#endif
4039
4040#if SANITIZER_INTERCEPT_SIGTIMEDWAIT
4041INTERCEPTOR(int, sigtimedwait, __sanitizer_sigset_t *set, void *info,
4042 void *timeout) {
4043 void *ctx;
4044 COMMON_INTERCEPTOR_ENTER(ctx, sigtimedwait, set, info, timeout);
4045 if (timeout) COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout, struct_timespec_sz);
4046 if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
4047 // FIXME: under ASan the call below may write to freed memory and corrupt
4048 // its metadata. See
4049 // https://github.com/google/sanitizers/issues/321.
4050 int res = REAL(sigtimedwait)(set, info, timeout);
4051 if (res > 0 && info) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, siginfo_t_sz);
4052 return res;
4053}
4054#define INIT_SIGTIMEDWAIT COMMON_INTERCEPT_FUNCTION(sigtimedwait);
4055#else
4056#define INIT_SIGTIMEDWAIT
4057#endif
4058
4059#if SANITIZER_INTERCEPT_SIGSETOPS
4060INTERCEPTOR(int, sigemptyset, __sanitizer_sigset_t *set) {
4061 void *ctx;
4062 COMMON_INTERCEPTOR_ENTER(ctx, sigemptyset, set);
4063 // FIXME: under ASan the call below may write to freed memory and corrupt
4064 // its metadata. See
4065 // https://github.com/google/sanitizers/issues/321.
4066 int res = REAL(sigemptyset)(set);
4067 if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set));
4068 return res;
4069}
4070
4071INTERCEPTOR(int, sigfillset, __sanitizer_sigset_t *set) {
4072 void *ctx;
4073 COMMON_INTERCEPTOR_ENTER(ctx, sigfillset, set);
4074 // FIXME: under ASan the call below may write to freed memory and corrupt
4075 // its metadata. See
4076 // https://github.com/google/sanitizers/issues/321.
4077 int res = REAL(sigfillset)(set);
4078 if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set));
4079 return res;
4080}
4081#define INIT_SIGSETOPS \
4082 COMMON_INTERCEPT_FUNCTION(sigemptyset); \
4083 COMMON_INTERCEPT_FUNCTION(sigfillset);
4084#else
4085#define INIT_SIGSETOPS
4086#endif
4087
4088#if SANITIZER_INTERCEPT_SIGPENDING
4089INTERCEPTOR(int, sigpending, __sanitizer_sigset_t *set) {
4090 void *ctx;
4091 COMMON_INTERCEPTOR_ENTER(ctx, sigpending, set);
4092 // FIXME: under ASan the call below may write to freed memory and corrupt
4093 // its metadata. See
4094 // https://github.com/google/sanitizers/issues/321.
4095 int res = REAL(sigpending)(set);
4096 if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set));
4097 return res;
4098}
4099#define INIT_SIGPENDING COMMON_INTERCEPT_FUNCTION(sigpending);
4100#else
4101#define INIT_SIGPENDING
4102#endif
4103
4104#if SANITIZER_INTERCEPT_SIGPROCMASK
4105INTERCEPTOR(int, sigprocmask, int how, __sanitizer_sigset_t *set,
4106 __sanitizer_sigset_t *oldset) {
4107 void *ctx;
4108 COMMON_INTERCEPTOR_ENTER(ctx, sigprocmask, how, set, oldset);
4109 if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
4110 // FIXME: under ASan the call below may write to freed memory and corrupt
4111 // its metadata. See
4112 // https://github.com/google/sanitizers/issues/321.
4113 int res = REAL(sigprocmask)(how, set, oldset);
4114 if (!res && oldset)
4115 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldset, sizeof(*oldset));
4116 return res;
4117}
4118#define INIT_SIGPROCMASK COMMON_INTERCEPT_FUNCTION(sigprocmask);
4119#else
4120#define INIT_SIGPROCMASK
4121#endif
4122
4123#if SANITIZER_INTERCEPT_PTHREAD_SIGMASK
4124INTERCEPTOR(int, pthread_sigmask, int how, __sanitizer_sigset_t *set,
4125 __sanitizer_sigset_t *oldset) {
4126 void *ctx;
4127 COMMON_INTERCEPTOR_ENTER(ctx, pthread_sigmask, how, set, oldset);
4128 if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
4129 // FIXME: under ASan the call below may write to freed memory and corrupt
4130 // its metadata. See
4131 // https://github.com/google/sanitizers/issues/321.
4132 int res = REAL(pthread_sigmask)(how, set, oldset);
4133 if (!res && oldset)
4134 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldset, sizeof(*oldset));
4135 return res;
4136}
4137#define INIT_PTHREAD_SIGMASK COMMON_INTERCEPT_FUNCTION(pthread_sigmask);
4138#else
4139#define INIT_PTHREAD_SIGMASK
4140#endif
4141
4142#if SANITIZER_INTERCEPT_BACKTRACE
4143INTERCEPTOR(int, backtrace, void **buffer, int size) {
4144 void *ctx;
4145 COMMON_INTERCEPTOR_ENTER(ctx, backtrace, buffer, size);
4146 // FIXME: under ASan the call below may write to freed memory and corrupt
4147 // its metadata. See
4148 // https://github.com/google/sanitizers/issues/321.
4149 int res = REAL(backtrace)(buffer, size);
4150 if (res && buffer)
4151 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buffer, res * sizeof(*buffer));
4152 return res;
4153}
4154
4155INTERCEPTOR(char **, backtrace_symbols, void **buffer, int size) {
4156 void *ctx;
4157 COMMON_INTERCEPTOR_ENTER(ctx, backtrace_symbols, buffer, size);
4158 if (buffer && size)
4159 COMMON_INTERCEPTOR_READ_RANGE(ctx, buffer, size * sizeof(*buffer));
4160 // FIXME: under ASan the call below may write to freed memory and corrupt
4161 // its metadata. See
4162 // https://github.com/google/sanitizers/issues/321.
4163 char **res = REAL(backtrace_symbols)(buffer, size);
4164 if (res && size) {
4165 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, size * sizeof(*res));
4166 for (int i = 0; i < size; ++i)
4167 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res[i], REAL(strlen(res[i])) + 1);
4168 }
4169 return res;
4170}
4171#define INIT_BACKTRACE \
4172 COMMON_INTERCEPT_FUNCTION(backtrace); \
4173 COMMON_INTERCEPT_FUNCTION(backtrace_symbols);
4174#else
4175#define INIT_BACKTRACE
4176#endif
4177
4178#if SANITIZER_INTERCEPT__EXIT
4179INTERCEPTOR(void, _exit, int status) {
4180 void *ctx;
4181 COMMON_INTERCEPTOR_ENTER(ctx, _exit, status);
4182 COMMON_INTERCEPTOR_USER_CALLBACK_START();
4183 int status1 = COMMON_INTERCEPTOR_ON_EXIT(ctx);
4184 COMMON_INTERCEPTOR_USER_CALLBACK_END();
4185 if (status == 0) status = status1;
4186 REAL(_exit)(status);
4187}
4188#define INIT__EXIT COMMON_INTERCEPT_FUNCTION(_exit);
4189#else
4190#define INIT__EXIT
4191#endif
4192
4193#if SANITIZER_INTERCEPT_PTHREAD_MUTEX
4194INTERCEPTOR(int, pthread_mutex_lock, void *m) {
4195 void *ctx;
4196 COMMON_INTERCEPTOR_ENTER(ctx, pthread_mutex_lock, m);
4197 COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m);
4198 int res = REAL(pthread_mutex_lock)(m);
4199 if (res == errno_EOWNERDEAD)
4200 COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m);
4201 if (res == 0 || res == errno_EOWNERDEAD)
4202 COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m);
4203 if (res == errno_EINVAL)
4204 COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m);
4205 return res;
4206}
4207
4208INTERCEPTOR(int, pthread_mutex_unlock, void *m) {
4209 void *ctx;
4210 COMMON_INTERCEPTOR_ENTER(ctx, pthread_mutex_unlock, m);
4211 COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m);
4212 int res = REAL(pthread_mutex_unlock)(m);
4213 if (res == errno_EINVAL)
4214 COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m);
4215 return res;
4216}
4217
4218#define INIT_PTHREAD_MUTEX_LOCK COMMON_INTERCEPT_FUNCTION(pthread_mutex_lock)
4219#define INIT_PTHREAD_MUTEX_UNLOCK \
4220 COMMON_INTERCEPT_FUNCTION(pthread_mutex_unlock)
4221#else
4222#define INIT_PTHREAD_MUTEX_LOCK
4223#define INIT_PTHREAD_MUTEX_UNLOCK
4224#endif
4225
4226#if SANITIZER_INTERCEPT___PTHREAD_MUTEX
4227INTERCEPTOR(int, __pthread_mutex_lock, void *m) {
4228 void *ctx;
4229 COMMON_INTERCEPTOR_ENTER(ctx, __pthread_mutex_lock, m);
4230 COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m);
4231 int res = REAL(__pthread_mutex_lock)(m);
4232 if (res == errno_EOWNERDEAD)
4233 COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m);
4234 if (res == 0 || res == errno_EOWNERDEAD)
4235 COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m);
4236 if (res == errno_EINVAL)
4237 COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m);
4238 return res;
4239}
4240
4241INTERCEPTOR(int, __pthread_mutex_unlock, void *m) {
4242 void *ctx;
4243 COMMON_INTERCEPTOR_ENTER(ctx, __pthread_mutex_unlock, m);
4244 COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m);
4245 int res = REAL(__pthread_mutex_unlock)(m);
4246 if (res == errno_EINVAL)
4247 COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m);
4248 return res;
4249}
4250
4251#define INIT___PTHREAD_MUTEX_LOCK \
4252 COMMON_INTERCEPT_FUNCTION(__pthread_mutex_lock)
4253#define INIT___PTHREAD_MUTEX_UNLOCK \
4254 COMMON_INTERCEPT_FUNCTION(__pthread_mutex_unlock)
4255#else
4256#define INIT___PTHREAD_MUTEX_LOCK
4257#define INIT___PTHREAD_MUTEX_UNLOCK
4258#endif
4259
4260#if SANITIZER_INTERCEPT___LIBC_MUTEX
4261INTERCEPTOR(int, __libc_mutex_lock, void *m)
4262ALIAS(WRAPPER_NAME(pthread_mutex_lock));
4263
4264INTERCEPTOR(int, __libc_mutex_unlock, void *m)
4265ALIAS(WRAPPER_NAME(pthread_mutex_unlock));
4266
4267INTERCEPTOR(int, __libc_thr_setcancelstate, int state, int *oldstate)
4268ALIAS(WRAPPER_NAME(pthread_setcancelstate));
4269
4270#define INIT___LIBC_MUTEX_LOCK COMMON_INTERCEPT_FUNCTION(__libc_mutex_lock)
4271#define INIT___LIBC_MUTEX_UNLOCK COMMON_INTERCEPT_FUNCTION(__libc_mutex_unlock)
4272#define INIT___LIBC_THR_SETCANCELSTATE \
4273 COMMON_INTERCEPT_FUNCTION(__libc_thr_setcancelstate)
4274#else
4275#define INIT___LIBC_MUTEX_LOCK
4276#define INIT___LIBC_MUTEX_UNLOCK
4277#define INIT___LIBC_THR_SETCANCELSTATE
4278#endif
4279
4280#if SANITIZER_INTERCEPT_GETMNTENT || SANITIZER_INTERCEPT_GETMNTENT_R
4281static void write_mntent(void *ctx, __sanitizer_mntent *mnt) {
4282 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt, sizeof(*mnt));
4283 if (mnt->mnt_fsname)
4284 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_fsname,
4285 REAL(strlen)(mnt->mnt_fsname) + 1);
4286 if (mnt->mnt_dir)
4287 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_dir,
4288 REAL(strlen)(mnt->mnt_dir) + 1);
4289 if (mnt->mnt_type)
4290 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_type,
4291 REAL(strlen)(mnt->mnt_type) + 1);
4292 if (mnt->mnt_opts)
4293 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_opts,
4294 REAL(strlen)(mnt->mnt_opts) + 1);
4295}
4296#endif
4297
4298#if SANITIZER_INTERCEPT_GETMNTENT
4299INTERCEPTOR(__sanitizer_mntent *, getmntent, void *fp) {
4300 void *ctx;
4301 COMMON_INTERCEPTOR_ENTER(ctx, getmntent, fp);
4302 __sanitizer_mntent *res = REAL(getmntent)(fp);
4303 if (res) write_mntent(ctx, res);
4304 return res;
4305}
4306#define INIT_GETMNTENT COMMON_INTERCEPT_FUNCTION(getmntent);
4307#else
4308#define INIT_GETMNTENT
4309#endif
4310
4311#if SANITIZER_INTERCEPT_GETMNTENT_R
4312INTERCEPTOR(__sanitizer_mntent *, getmntent_r, void *fp,
4313 __sanitizer_mntent *mntbuf, char *buf, int buflen) {
4314 void *ctx;
4315 COMMON_INTERCEPTOR_ENTER(ctx, getmntent_r, fp, mntbuf, buf, buflen);
4316 __sanitizer_mntent *res = REAL(getmntent_r)(fp, mntbuf, buf, buflen);
4317 if (res) write_mntent(ctx, res);
4318 return res;
4319}
4320#define INIT_GETMNTENT_R COMMON_INTERCEPT_FUNCTION(getmntent_r);
4321#else
4322#define INIT_GETMNTENT_R
4323#endif
4324
4325#if SANITIZER_INTERCEPT_STATFS
4326INTERCEPTOR(int, statfs, char *path, void *buf) {
4327 void *ctx;
4328 COMMON_INTERCEPTOR_ENTER(ctx, statfs, path, buf);
4329 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
4330 // FIXME: under ASan the call below may write to freed memory and corrupt
4331 // its metadata. See
4332 // https://github.com/google/sanitizers/issues/321.
4333 int res = REAL(statfs)(path, buf);
4334 if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs_sz);
4335 return res;
4336}
4337INTERCEPTOR(int, fstatfs, int fd, void *buf) {
4338 void *ctx;
4339 COMMON_INTERCEPTOR_ENTER(ctx, fstatfs, fd, buf);
4340 // FIXME: under ASan the call below may write to freed memory and corrupt
4341 // its metadata. See
4342 // https://github.com/google/sanitizers/issues/321.
4343 int res = REAL(fstatfs)(fd, buf);
4344 if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs_sz);
4345 return res;
4346}
4347#define INIT_STATFS \
4348 COMMON_INTERCEPT_FUNCTION(statfs); \
4349 COMMON_INTERCEPT_FUNCTION(fstatfs);
4350#else
4351#define INIT_STATFS
4352#endif
4353
4354#if SANITIZER_INTERCEPT_STATFS64
4355INTERCEPTOR(int, statfs64, char *path, void *buf) {
4356 void *ctx;
4357 COMMON_INTERCEPTOR_ENTER(ctx, statfs64, path, buf);
4358 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
4359 // FIXME: under ASan the call below may write to freed memory and corrupt
4360 // its metadata. See
4361 // https://github.com/google/sanitizers/issues/321.
4362 int res = REAL(statfs64)(path, buf);
4363 if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs64_sz);
4364 return res;
4365}
4366INTERCEPTOR(int, fstatfs64, int fd, void *buf) {
4367 void *ctx;
4368 COMMON_INTERCEPTOR_ENTER(ctx, fstatfs64, fd, buf);
4369 // FIXME: under ASan the call below may write to freed memory and corrupt
4370 // its metadata. See
4371 // https://github.com/google/sanitizers/issues/321.
4372 int res = REAL(fstatfs64)(fd, buf);
4373 if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs64_sz);
4374 return res;
4375}
4376#define INIT_STATFS64 \
4377 COMMON_INTERCEPT_FUNCTION(statfs64); \
4378 COMMON_INTERCEPT_FUNCTION(fstatfs64);
4379#else
4380#define INIT_STATFS64
4381#endif
4382
4383#if SANITIZER_INTERCEPT_STATVFS
4384INTERCEPTOR(int, statvfs, char *path, void *buf) {
4385 void *ctx;
4386 COMMON_INTERCEPTOR_ENTER(ctx, statvfs, path, buf);
4387 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
4388 // FIXME: under ASan the call below may write to freed memory and corrupt
4389 // its metadata. See
4390 // https://github.com/google/sanitizers/issues/321.
4391 int res = REAL(statvfs)(path, buf);
4392 if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz);
4393 return res;
4394}
4395INTERCEPTOR(int, fstatvfs, int fd, void *buf) {
4396 void *ctx;
4397 COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs, fd, buf);
4398 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
4399 // FIXME: under ASan the call below may write to freed memory and corrupt
4400 // its metadata. See
4401 // https://github.com/google/sanitizers/issues/321.
4402 int res = REAL(fstatvfs)(fd, buf);
4403 if (!res) {
4404 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz);
4405 if (fd >= 0)
4406 COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
4407 }
4408 return res;
4409}
4410#define INIT_STATVFS \
4411 COMMON_INTERCEPT_FUNCTION(statvfs); \
4412 COMMON_INTERCEPT_FUNCTION(fstatvfs);
4413#else
4414#define INIT_STATVFS
4415#endif
4416
4417#if SANITIZER_INTERCEPT_STATVFS64
4418INTERCEPTOR(int, statvfs64, char *path, void *buf) {
4419 void *ctx;
4420 COMMON_INTERCEPTOR_ENTER(ctx, statvfs64, path, buf);
4421 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
4422 // FIXME: under ASan the call below may write to freed memory and corrupt
4423 // its metadata. See
4424 // https://github.com/google/sanitizers/issues/321.
4425 int res = REAL(statvfs64)(path, buf);
4426 if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs64_sz);
4427 return res;
4428}
4429INTERCEPTOR(int, fstatvfs64, int fd, void *buf) {
4430 void *ctx;
4431 COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs64, fd, buf);
4432 // FIXME: under ASan the call below may write to freed memory and corrupt
4433 // its metadata. See
4434 // https://github.com/google/sanitizers/issues/321.
4435 int res = REAL(fstatvfs64)(fd, buf);
4436 if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs64_sz);
4437 return res;
4438}
4439#define INIT_STATVFS64 \
4440 COMMON_INTERCEPT_FUNCTION(statvfs64); \
4441 COMMON_INTERCEPT_FUNCTION(fstatvfs64);
4442#else
4443#define INIT_STATVFS64
4444#endif
4445
4446#if SANITIZER_INTERCEPT_INITGROUPS
4447INTERCEPTOR(int, initgroups, char *user, u32 group) {
4448 void *ctx;
4449 COMMON_INTERCEPTOR_ENTER(ctx, initgroups, user, group);
4450 if (user) COMMON_INTERCEPTOR_READ_RANGE(ctx, user, REAL(strlen)(user) + 1);
4451 int res = REAL(initgroups)(user, group);
4452 return res;
4453}
4454#define INIT_INITGROUPS COMMON_INTERCEPT_FUNCTION(initgroups);
4455#else
4456#define INIT_INITGROUPS
4457#endif
4458
4459#if SANITIZER_INTERCEPT_ETHER_NTOA_ATON
4460INTERCEPTOR(char *, ether_ntoa, __sanitizer_ether_addr *addr) {
4461 void *ctx;
4462 COMMON_INTERCEPTOR_ENTER(ctx, ether_ntoa, addr);
4463 if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr));
4464 char *res = REAL(ether_ntoa)(addr);
4465 if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
4466 return res;
4467}
4468INTERCEPTOR(__sanitizer_ether_addr *, ether_aton, char *buf) {
4469 void *ctx;
4470 COMMON_INTERCEPTOR_ENTER(ctx, ether_aton, buf);
4471 if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
4472 __sanitizer_ether_addr *res = REAL(ether_aton)(buf);
4473 if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, sizeof(*res));
4474 return res;
4475}
4476#define INIT_ETHER_NTOA_ATON \
4477 COMMON_INTERCEPT_FUNCTION(ether_ntoa); \
4478 COMMON_INTERCEPT_FUNCTION(ether_aton);
4479#else
4480#define INIT_ETHER_NTOA_ATON
4481#endif
4482
4483#if SANITIZER_INTERCEPT_ETHER_HOST
4484INTERCEPTOR(int, ether_ntohost, char *hostname, __sanitizer_ether_addr *addr) {
4485 void *ctx;
4486 COMMON_INTERCEPTOR_ENTER(ctx, ether_ntohost, hostname, addr);
4487 if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr));
4488 // FIXME: under ASan the call below may write to freed memory and corrupt
4489 // its metadata. See
4490 // https://github.com/google/sanitizers/issues/321.
4491 int res = REAL(ether_ntohost)(hostname, addr);
4492 if (!res && hostname)
4493 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hostname, REAL(strlen)(hostname) + 1);
4494 return res;
4495}
4496INTERCEPTOR(int, ether_hostton, char *hostname, __sanitizer_ether_addr *addr) {
4497 void *ctx;
4498 COMMON_INTERCEPTOR_ENTER(ctx, ether_hostton, hostname, addr);
4499 if (hostname)
4500 COMMON_INTERCEPTOR_READ_RANGE(ctx, hostname, REAL(strlen)(hostname) + 1);
4501 // FIXME: under ASan the call below may write to freed memory and corrupt
4502 // its metadata. See
4503 // https://github.com/google/sanitizers/issues/321.
4504 int res = REAL(ether_hostton)(hostname, addr);
4505 if (!res && addr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, sizeof(*addr));
4506 return res;
4507}
4508INTERCEPTOR(int, ether_line, char *line, __sanitizer_ether_addr *addr,
4509 char *hostname) {
4510 void *ctx;
4511 COMMON_INTERCEPTOR_ENTER(ctx, ether_line, line, addr, hostname);
4512 if (line) COMMON_INTERCEPTOR_READ_RANGE(ctx, line, REAL(strlen)(line) + 1);
4513 // FIXME: under ASan the call below may write to freed memory and corrupt
4514 // its metadata. See
4515 // https://github.com/google/sanitizers/issues/321.
4516 int res = REAL(ether_line)(line, addr, hostname);
4517 if (!res) {
4518 if (addr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, sizeof(*addr));
4519 if (hostname)
4520 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hostname, REAL(strlen)(hostname) + 1);
4521 }
4522 return res;
4523}
4524#define INIT_ETHER_HOST \
4525 COMMON_INTERCEPT_FUNCTION(ether_ntohost); \
4526 COMMON_INTERCEPT_FUNCTION(ether_hostton); \
4527 COMMON_INTERCEPT_FUNCTION(ether_line);
4528#else
4529#define INIT_ETHER_HOST
4530#endif
4531
4532#if SANITIZER_INTERCEPT_ETHER_R
4533INTERCEPTOR(char *, ether_ntoa_r, __sanitizer_ether_addr *addr, char *buf) {
4534 void *ctx;
4535 COMMON_INTERCEPTOR_ENTER(ctx, ether_ntoa_r, addr, buf);
4536 if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr));
4537 // FIXME: under ASan the call below may write to freed memory and corrupt
4538 // its metadata. See
4539 // https://github.com/google/sanitizers/issues/321.
4540 char *res = REAL(ether_ntoa_r)(addr, buf);
4541 if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
4542 return res;
4543}
4544INTERCEPTOR(__sanitizer_ether_addr *, ether_aton_r, char *buf,
4545 __sanitizer_ether_addr *addr) {
4546 void *ctx;
4547 COMMON_INTERCEPTOR_ENTER(ctx, ether_aton_r, buf, addr);
4548 if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
4549 // FIXME: under ASan the call below may write to freed memory and corrupt
4550 // its metadata. See
4551 // https://github.com/google/sanitizers/issues/321.
4552 __sanitizer_ether_addr *res = REAL(ether_aton_r)(buf, addr);
4553 if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, sizeof(*res));
4554 return res;
4555}
4556#define INIT_ETHER_R \
4557 COMMON_INTERCEPT_FUNCTION(ether_ntoa_r); \
4558 COMMON_INTERCEPT_FUNCTION(ether_aton_r);
4559#else
4560#define INIT_ETHER_R
4561#endif
4562
4563#if SANITIZER_INTERCEPT_SHMCTL
4564INTERCEPTOR(int, shmctl, int shmid, int cmd, void *buf) {
4565 void *ctx;
4566 COMMON_INTERCEPTOR_ENTER(ctx, shmctl, shmid, cmd, buf);
4567 // FIXME: under ASan the call below may write to freed memory and corrupt
4568 // its metadata. See
4569 // https://github.com/google/sanitizers/issues/321.
4570 int res = REAL(shmctl)(shmid, cmd, buf);
4571 if (res >= 0) {
4572 unsigned sz = 0;
4573 if (cmd == shmctl_ipc_stat || cmd == shmctl_shm_stat)
4574 sz = sizeof(__sanitizer_shmid_ds);
4575 else if (cmd == shmctl_ipc_info)
4576 sz = struct_shminfo_sz;
4577 else if (cmd == shmctl_shm_info)
4578 sz = struct_shm_info_sz;
4579 if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sz);
4580 }
4581 return res;
4582}
4583#define INIT_SHMCTL COMMON_INTERCEPT_FUNCTION(shmctl);
4584#else
4585#define INIT_SHMCTL
4586#endif
4587
4588#if SANITIZER_INTERCEPT_RANDOM_R
4589INTERCEPTOR(int, random_r, void *buf, u32 *result) {
4590 void *ctx;
4591 COMMON_INTERCEPTOR_ENTER(ctx, random_r, buf, result);
4592 // FIXME: under ASan the call below may write to freed memory and corrupt
4593 // its metadata. See
4594 // https://github.com/google/sanitizers/issues/321.
4595 int res = REAL(random_r)(buf, result);
4596 if (!res && result)
4597 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
4598 return res;
4599}
4600#define INIT_RANDOM_R COMMON_INTERCEPT_FUNCTION(random_r);
4601#else
4602#define INIT_RANDOM_R
4603#endif
4604
4605// FIXME: under ASan the REAL() call below may write to freed memory and corrupt
4606// its metadata. See
4607// https://github.com/google/sanitizers/issues/321.
4608#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GET || \
4609 SANITIZER_INTERCEPT_PTHREAD_ATTR_GET_SCHED || \
4610 SANITIZER_INTERCEPT_PTHREAD_ATTR_GETINHERITSSCHED || \
4611 SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GET || \
4612 SANITIZER_INTERCEPT_PTHREAD_RWLOCKATTR_GET || \
4613 SANITIZER_INTERCEPT_PTHREAD_CONDATTR_GET || \
4614 SANITIZER_INTERCEPT_PTHREAD_BARRIERATTR_GET
4615#define INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(fn, sz) \
4616 INTERCEPTOR(int, fn, void *attr, void *r) { \
4617 void *ctx; \
4618 COMMON_INTERCEPTOR_ENTER(ctx, fn, attr, r); \
4619 int res = REAL(fn)(attr, r); \
4620 if (!res && r) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, r, sz); \
4621 return res; \
4622 }
4623#define INTERCEPTOR_PTHREAD_ATTR_GET(what, sz) \
4624 INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_attr_get##what, sz)
4625#define INTERCEPTOR_PTHREAD_MUTEXATTR_GET(what, sz) \
4626 INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_mutexattr_get##what, sz)
4627#define INTERCEPTOR_PTHREAD_RWLOCKATTR_GET(what, sz) \
4628 INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_rwlockattr_get##what, sz)
4629#define INTERCEPTOR_PTHREAD_CONDATTR_GET(what, sz) \
4630 INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_condattr_get##what, sz)
4631#define INTERCEPTOR_PTHREAD_BARRIERATTR_GET(what, sz) \
4632 INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_barrierattr_get##what, sz)
4633#endif
4634
4635#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GET
4636INTERCEPTOR_PTHREAD_ATTR_GET(detachstate, sizeof(int))
4637INTERCEPTOR_PTHREAD_ATTR_GET(guardsize, sizeof(SIZE_T))
4638INTERCEPTOR_PTHREAD_ATTR_GET(scope, sizeof(int))
4639INTERCEPTOR_PTHREAD_ATTR_GET(stacksize, sizeof(SIZE_T))
4640INTERCEPTOR(int, pthread_attr_getstack, void *attr, void **addr, SIZE_T *size) {
4641 void *ctx;
4642 COMMON_INTERCEPTOR_ENTER(ctx, pthread_attr_getstack, attr, addr, size);
4643 // FIXME: under ASan the call below may write to freed memory and corrupt
4644 // its metadata. See
4645 // https://github.com/google/sanitizers/issues/321.
4646 int res = REAL(pthread_attr_getstack)(attr, addr, size);
4647 if (!res) {
4648 if (addr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, sizeof(*addr));
4649 if (size) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, size, sizeof(*size));
4650 }
4651 return res;
4652}
4653
4654// We may need to call the real pthread_attr_getstack from the run-time
4655// in sanitizer_common, but we don't want to include the interception headers
4656// there. So, just define this function here.
4657namespace __sanitizer {
4658extern "C" {
4659int real_pthread_attr_getstack(void *attr, void **addr, SIZE_T *size) {
4660 return REAL(pthread_attr_getstack)(attr, addr, size);
4661}
4662} // extern "C"
4663} // namespace __sanitizer
4664
4665#define INIT_PTHREAD_ATTR_GET \
4666 COMMON_INTERCEPT_FUNCTION(pthread_attr_getdetachstate); \
4667 COMMON_INTERCEPT_FUNCTION(pthread_attr_getguardsize); \
4668 COMMON_INTERCEPT_FUNCTION(pthread_attr_getscope); \
4669 COMMON_INTERCEPT_FUNCTION(pthread_attr_getstacksize); \
4670 COMMON_INTERCEPT_FUNCTION(pthread_attr_getstack);
4671#else
4672#define INIT_PTHREAD_ATTR_GET
4673#endif
4674
4675#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GET_SCHED
4676INTERCEPTOR_PTHREAD_ATTR_GET(schedparam, struct_sched_param_sz)
4677INTERCEPTOR_PTHREAD_ATTR_GET(schedpolicy, sizeof(int))
4678
4679#define INIT_PTHREAD_ATTR_GET_SCHED \
4680 COMMON_INTERCEPT_FUNCTION(pthread_attr_getschedparam); \
4681 COMMON_INTERCEPT_FUNCTION(pthread_attr_getschedpolicy);
4682#else
4683#define INIT_PTHREAD_ATTR_GET_SCHED
4684#endif
4685
4686#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GETINHERITSCHED
4687INTERCEPTOR_PTHREAD_ATTR_GET(inheritsched, sizeof(int))
4688
4689#define INIT_PTHREAD_ATTR_GETINHERITSCHED \
4690 COMMON_INTERCEPT_FUNCTION(pthread_attr_getinheritsched);
4691#else
4692#define INIT_PTHREAD_ATTR_GETINHERITSCHED
4693#endif
4694
4695#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GETAFFINITY_NP
4696INTERCEPTOR(int, pthread_attr_getaffinity_np, void *attr, SIZE_T cpusetsize,
4697 void *cpuset) {
4698 void *ctx;
4699 COMMON_INTERCEPTOR_ENTER(ctx, pthread_attr_getaffinity_np, attr, cpusetsize,
4700 cpuset);
4701 // FIXME: under ASan the call below may write to freed memory and corrupt
4702 // its metadata. See
4703 // https://github.com/google/sanitizers/issues/321.
4704 int res = REAL(pthread_attr_getaffinity_np)(attr, cpusetsize, cpuset);
4705 if (!res && cpusetsize && cpuset)
4706 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cpuset, cpusetsize);
4707 return res;
4708}
4709
4710#define INIT_PTHREAD_ATTR_GETAFFINITY_NP \
4711 COMMON_INTERCEPT_FUNCTION(pthread_attr_getaffinity_np);
4712#else
4713#define INIT_PTHREAD_ATTR_GETAFFINITY_NP
4714#endif
4715
4716#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPSHARED
4717INTERCEPTOR_PTHREAD_MUTEXATTR_GET(pshared, sizeof(int))
4718#define INIT_PTHREAD_MUTEXATTR_GETPSHARED \
4719 COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getpshared);
4720#else
4721#define INIT_PTHREAD_MUTEXATTR_GETPSHARED
4722#endif
4723
4724#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETTYPE
4725INTERCEPTOR_PTHREAD_MUTEXATTR_GET(type, sizeof(int))
4726#define INIT_PTHREAD_MUTEXATTR_GETTYPE \
4727 COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_gettype);
4728#else
4729#define INIT_PTHREAD_MUTEXATTR_GETTYPE
4730#endif
4731
4732#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPROTOCOL
4733INTERCEPTOR_PTHREAD_MUTEXATTR_GET(protocol, sizeof(int))
4734#define INIT_PTHREAD_MUTEXATTR_GETPROTOCOL \
4735 COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getprotocol);
4736#else
4737#define INIT_PTHREAD_MUTEXATTR_GETPROTOCOL
4738#endif
4739
4740#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPRIOCEILING
4741INTERCEPTOR_PTHREAD_MUTEXATTR_GET(prioceiling, sizeof(int))
4742#define INIT_PTHREAD_MUTEXATTR_GETPRIOCEILING \
4743 COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getprioceiling);
4744#else
4745#define INIT_PTHREAD_MUTEXATTR_GETPRIOCEILING
4746#endif
4747
4748#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETROBUST
4749INTERCEPTOR_PTHREAD_MUTEXATTR_GET(robust, sizeof(int))
4750#define INIT_PTHREAD_MUTEXATTR_GETROBUST \
4751 COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getrobust);
4752#else
4753#define INIT_PTHREAD_MUTEXATTR_GETROBUST
4754#endif
4755
4756#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETROBUST_NP
4757INTERCEPTOR_PTHREAD_MUTEXATTR_GET(robust_np, sizeof(int))
4758#define INIT_PTHREAD_MUTEXATTR_GETROBUST_NP \
4759 COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getrobust_np);
4760#else
4761#define INIT_PTHREAD_MUTEXATTR_GETROBUST_NP
4762#endif
4763
4764#if SANITIZER_INTERCEPT_PTHREAD_RWLOCKATTR_GETPSHARED
4765INTERCEPTOR_PTHREAD_RWLOCKATTR_GET(pshared, sizeof(int))
4766#define INIT_PTHREAD_RWLOCKATTR_GETPSHARED \
4767 COMMON_INTERCEPT_FUNCTION(pthread_rwlockattr_getpshared);
4768#else
4769#define INIT_PTHREAD_RWLOCKATTR_GETPSHARED
4770#endif
4771
4772#if SANITIZER_INTERCEPT_PTHREAD_RWLOCKATTR_GETKIND_NP
4773INTERCEPTOR_PTHREAD_RWLOCKATTR_GET(kind_np, sizeof(int))
4774#define INIT_PTHREAD_RWLOCKATTR_GETKIND_NP \
4775 COMMON_INTERCEPT_FUNCTION(pthread_rwlockattr_getkind_np);
4776#else
4777#define INIT_PTHREAD_RWLOCKATTR_GETKIND_NP
4778#endif
4779
4780#if SANITIZER_INTERCEPT_PTHREAD_CONDATTR_GETPSHARED
4781INTERCEPTOR_PTHREAD_CONDATTR_GET(pshared, sizeof(int))
4782#define INIT_PTHREAD_CONDATTR_GETPSHARED \
4783 COMMON_INTERCEPT_FUNCTION(pthread_condattr_getpshared);
4784#else
4785#define INIT_PTHREAD_CONDATTR_GETPSHARED
4786#endif
4787
4788#if SANITIZER_INTERCEPT_PTHREAD_CONDATTR_GETCLOCK
4789INTERCEPTOR_PTHREAD_CONDATTR_GET(clock, sizeof(int))
4790#define INIT_PTHREAD_CONDATTR_GETCLOCK \
4791 COMMON_INTERCEPT_FUNCTION(pthread_condattr_getclock);
4792#else
4793#define INIT_PTHREAD_CONDATTR_GETCLOCK
4794#endif
4795
4796#if SANITIZER_INTERCEPT_PTHREAD_BARRIERATTR_GETPSHARED
4797INTERCEPTOR_PTHREAD_BARRIERATTR_GET(pshared, sizeof(int)) // !mac !android
4798#define INIT_PTHREAD_BARRIERATTR_GETPSHARED \
4799 COMMON_INTERCEPT_FUNCTION(pthread_barrierattr_getpshared);
4800#else
4801#define INIT_PTHREAD_BARRIERATTR_GETPSHARED
4802#endif
4803
4804#if SANITIZER_INTERCEPT_TMPNAM
4805INTERCEPTOR(char *, tmpnam, char *s) {
4806 void *ctx;
4807 COMMON_INTERCEPTOR_ENTER(ctx, tmpnam, s);
4808 char *res = REAL(tmpnam)(s);
4809 if (res) {
4810 if (s)
4811 // FIXME: under ASan the call below may write to freed memory and corrupt
4812 // its metadata. See
4813 // https://github.com/google/sanitizers/issues/321.
4814 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, REAL(strlen)(s) + 1);
4815 else
4816 COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
4817 }
4818 return res;
4819}
4820#define INIT_TMPNAM COMMON_INTERCEPT_FUNCTION(tmpnam);
4821#else
4822#define INIT_TMPNAM
4823#endif
4824
4825#if SANITIZER_INTERCEPT_TMPNAM_R
4826INTERCEPTOR(char *, tmpnam_r, char *s) {
4827 void *ctx;
4828 COMMON_INTERCEPTOR_ENTER(ctx, tmpnam_r, s);
4829 // FIXME: under ASan the call below may write to freed memory and corrupt
4830 // its metadata. See
4831 // https://github.com/google/sanitizers/issues/321.
4832 char *res = REAL(tmpnam_r)(s);
4833 if (res && s) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, REAL(strlen)(s) + 1);
4834 return res;
4835}
4836#define INIT_TMPNAM_R COMMON_INTERCEPT_FUNCTION(tmpnam_r);
4837#else
4838#define INIT_TMPNAM_R
4839#endif
4840
4841#if SANITIZER_INTERCEPT_TTYNAME
4842INTERCEPTOR(char *, ttyname, int fd) {
4843 void *ctx;
4844 COMMON_INTERCEPTOR_ENTER(ctx, ttyname, fd);
4845 char *res = REAL(ttyname)(fd);
4846 if (res != nullptr)
4847 COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
4848 return res;
4849}
4850#define INIT_TTYNAME COMMON_INTERCEPT_FUNCTION(ttyname);
4851#else
4852#define INIT_TTYNAME
4853#endif
4854
4855#if SANITIZER_INTERCEPT_TTYNAME_R
4856INTERCEPTOR(int, ttyname_r, int fd, char *name, SIZE_T namesize) {
4857 void *ctx;
4858 COMMON_INTERCEPTOR_ENTER(ctx, ttyname_r, fd, name, namesize);
4859 int res = REAL(ttyname_r)(fd, name, namesize);
4860 if (res == 0)
4861 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, REAL(strlen)(name) + 1);
4862 return res;
4863}
4864#define INIT_TTYNAME_R COMMON_INTERCEPT_FUNCTION(ttyname_r);
4865#else
4866#define INIT_TTYNAME_R
4867#endif
4868
4869#if SANITIZER_INTERCEPT_TEMPNAM
4870INTERCEPTOR(char *, tempnam, char *dir, char *pfx) {
4871 void *ctx;
4872 COMMON_INTERCEPTOR_ENTER(ctx, tempnam, dir, pfx);
4873 if (dir) COMMON_INTERCEPTOR_READ_RANGE(ctx, dir, REAL(strlen)(dir) + 1);
4874 if (pfx) COMMON_INTERCEPTOR_READ_RANGE(ctx, pfx, REAL(strlen)(pfx) + 1);
4875 char *res = REAL(tempnam)(dir, pfx);
4876 if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
4877 return res;
4878}
4879#define INIT_TEMPNAM COMMON_INTERCEPT_FUNCTION(tempnam);
4880#else
4881#define INIT_TEMPNAM
4882#endif
4883
4884#if SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP && !SANITIZER_NETBSD
4885INTERCEPTOR(int, pthread_setname_np, uptr thread, const char *name) {
4886 void *ctx;
4887 COMMON_INTERCEPTOR_ENTER(ctx, pthread_setname_np, thread, name);
4888 COMMON_INTERCEPTOR_READ_STRING(ctx, name, 0);
4889 COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name);
4890 return REAL(pthread_setname_np)(thread, name);
4891}
4892#define INIT_PTHREAD_SETNAME_NP COMMON_INTERCEPT_FUNCTION(pthread_setname_np);
4893#elif SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP && SANITIZER_NETBSD
4894INTERCEPTOR(int, pthread_setname_np, uptr thread, const char *name, void *arg) {
4895 void *ctx;
4896 char newname[32]; // PTHREAD_MAX_NAMELEN_NP=32
4897 COMMON_INTERCEPTOR_ENTER(ctx, pthread_setname_np, thread, name, arg);
4898 COMMON_INTERCEPTOR_READ_STRING(ctx, name, 0);
4899 internal_snprintf(newname, sizeof(newname), name, arg);
4900 COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, newname);
4901 return REAL(pthread_setname_np)(thread, name, arg);
4902}
4903#define INIT_PTHREAD_SETNAME_NP COMMON_INTERCEPT_FUNCTION(pthread_setname_np);
4904#else
4905#define INIT_PTHREAD_SETNAME_NP
4906#endif
4907
4908#if SANITIZER_INTERCEPT_PTHREAD_GETNAME_NP
4909INTERCEPTOR(int, pthread_getname_np, uptr thread, char *name, SIZE_T len) {
4910 void *ctx;
4911 COMMON_INTERCEPTOR_ENTER(ctx, pthread_getname_np, thread, name, len);
4912 int res = REAL(pthread_getname_np)(thread, name, len);
4913 if (!res)
4914 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strnlen(name, len) + 1);
4915 return res;
4916}
4917#define INIT_PTHREAD_GETNAME_NP COMMON_INTERCEPT_FUNCTION(pthread_getname_np);
4918#else
4919#define INIT_PTHREAD_GETNAME_NP
4920#endif
4921
4922#if SANITIZER_INTERCEPT_SINCOS
4923INTERCEPTOR(void, sincos, double x, double *sin, double *cos) {
4924 void *ctx;
4925 COMMON_INTERCEPTOR_ENTER(ctx, sincos, x, sin, cos);
4926 // FIXME: under ASan the call below may write to freed memory and corrupt
4927 // its metadata. See
4928 // https://github.com/google/sanitizers/issues/321.
4929 REAL(sincos)(x, sin, cos);
4930 if (sin) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sin, sizeof(*sin));
4931 if (cos) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cos, sizeof(*cos));
4932}
4933INTERCEPTOR(void, sincosf, float x, float *sin, float *cos) {
4934 void *ctx;
4935 COMMON_INTERCEPTOR_ENTER(ctx, sincosf, x, sin, cos);
4936 // FIXME: under ASan the call below may write to freed memory and corrupt
4937 // its metadata. See
4938 // https://github.com/google/sanitizers/issues/321.
4939 REAL(sincosf)(x, sin, cos);
4940 if (sin) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sin, sizeof(*sin));
4941 if (cos) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cos, sizeof(*cos));
4942}
4943INTERCEPTOR(void, sincosl, long double x, long double *sin, long double *cos) {
4944 void *ctx;
4945 COMMON_INTERCEPTOR_ENTER(ctx, sincosl, x, sin, cos);
4946 // FIXME: under ASan the call below may write to freed memory and corrupt
4947 // its metadata. See
4948 // https://github.com/google/sanitizers/issues/321.
4949 REAL(sincosl)(x, sin, cos);
4950 if (sin) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sin, sizeof(*sin));
4951 if (cos) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cos, sizeof(*cos));
4952}
4953#define INIT_SINCOS \
4954 COMMON_INTERCEPT_FUNCTION(sincos); \
4955 COMMON_INTERCEPT_FUNCTION(sincosf); \
4956 COMMON_INTERCEPT_FUNCTION_LDBL(sincosl);
4957#else
4958#define INIT_SINCOS
4959#endif
4960
4961#if SANITIZER_INTERCEPT_REMQUO
4962INTERCEPTOR(double, remquo, double x, double y, int *quo) {
4963 void *ctx;
4964 COMMON_INTERCEPTOR_ENTER(ctx, remquo, x, y, quo);
4965 // FIXME: under ASan the call below may write to freed memory and corrupt
4966 // its metadata. See
4967 // https://github.com/google/sanitizers/issues/321.
4968 double res = REAL(remquo)(x, y, quo);
4969 if (quo) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, quo, sizeof(*quo));
4970 return res;
4971}
4972INTERCEPTOR(float, remquof, float x, float y, int *quo) {
4973 void *ctx;
4974 COMMON_INTERCEPTOR_ENTER(ctx, remquof, x, y, quo);
4975 // FIXME: under ASan the call below may write to freed memory and corrupt
4976 // its metadata. See
4977 // https://github.com/google/sanitizers/issues/321.
4978 float res = REAL(remquof)(x, y, quo);
4979 if (quo) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, quo, sizeof(*quo));
4980 return res;
4981}
4982#define INIT_REMQUO \
4983 COMMON_INTERCEPT_FUNCTION(remquo); \
4984 COMMON_INTERCEPT_FUNCTION(remquof);
4985#else
4986#define INIT_REMQUO
4987#endif
4988
4989#if SANITIZER_INTERCEPT_REMQUOL
4990INTERCEPTOR(long double, remquol, long double x, long double y, int *quo) {
4991 void *ctx;
4992 COMMON_INTERCEPTOR_ENTER(ctx, remquol, x, y, quo);
4993 // FIXME: under ASan the call below may write to freed memory and corrupt
4994 // its metadata. See
4995 // https://github.com/google/sanitizers/issues/321.
4996 long double res = REAL(remquol)(x, y, quo);
4997 if (quo) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, quo, sizeof(*quo));
4998 return res;
4999}
5000#define INIT_REMQUOL \
5001 COMMON_INTERCEPT_FUNCTION_LDBL(remquol);
5002#else
5003#define INIT_REMQUOL
5004#endif
5005
5006#if SANITIZER_INTERCEPT_LGAMMA
5007extern int signgam;
5008INTERCEPTOR(double, lgamma, double x) {
5009 void *ctx;
5010 COMMON_INTERCEPTOR_ENTER(ctx, lgamma, x);
5011 double res = REAL(lgamma)(x);
5012 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &signgam, sizeof(signgam));
5013 return res;
5014}
5015INTERCEPTOR(float, lgammaf, float x) {
5016 void *ctx;
5017 COMMON_INTERCEPTOR_ENTER(ctx, lgammaf, x);
5018 float res = REAL(lgammaf)(x);
5019 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &signgam, sizeof(signgam));
5020 return res;
5021}
5022#define INIT_LGAMMA \
5023 COMMON_INTERCEPT_FUNCTION(lgamma); \
5024 COMMON_INTERCEPT_FUNCTION(lgammaf);
5025#else
5026#define INIT_LGAMMA
5027#endif
5028
5029#if SANITIZER_INTERCEPT_LGAMMAL
5030INTERCEPTOR(long double, lgammal, long double x) {
5031 void *ctx;
5032 COMMON_INTERCEPTOR_ENTER(ctx, lgammal, x);
5033 long double res = REAL(lgammal)(x);
5034 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &signgam, sizeof(signgam));
5035 return res;
5036}
5037#define INIT_LGAMMAL \
5038 COMMON_INTERCEPT_FUNCTION_LDBL(lgammal);
5039#else
5040#define INIT_LGAMMAL
5041#endif
5042
5043#if SANITIZER_INTERCEPT_LGAMMA_R
5044INTERCEPTOR(double, lgamma_r, double x, int *signp) {
5045 void *ctx;
5046 COMMON_INTERCEPTOR_ENTER(ctx, lgamma_r, x, signp);
5047 // FIXME: under ASan the call below may write to freed memory and corrupt
5048 // its metadata. See
5049 // https://github.com/google/sanitizers/issues/321.
5050 double res = REAL(lgamma_r)(x, signp);
5051 if (signp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, signp, sizeof(*signp));
5052 return res;
5053}
5054INTERCEPTOR(float, lgammaf_r, float x, int *signp) {
5055 void *ctx;
5056 COMMON_INTERCEPTOR_ENTER(ctx, lgammaf_r, x, signp);
5057 // FIXME: under ASan the call below may write to freed memory and corrupt
5058 // its metadata. See
5059 // https://github.com/google/sanitizers/issues/321.
5060 float res = REAL(lgammaf_r)(x, signp);
5061 if (signp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, signp, sizeof(*signp));
5062 return res;
5063}
5064#define INIT_LGAMMA_R \
5065 COMMON_INTERCEPT_FUNCTION(lgamma_r); \
5066 COMMON_INTERCEPT_FUNCTION(lgammaf_r);
5067#else
5068#define INIT_LGAMMA_R
5069#endif
5070
5071#if SANITIZER_INTERCEPT_LGAMMAL_R
5072INTERCEPTOR(long double, lgammal_r, long double x, int *signp) {
5073 void *ctx;
5074 COMMON_INTERCEPTOR_ENTER(ctx, lgammal_r, x, signp);
5075 // FIXME: under ASan the call below may write to freed memory and corrupt
5076 // its metadata. See
5077 // https://github.com/google/sanitizers/issues/321.
5078 long double res = REAL(lgammal_r)(x, signp);
5079 if (signp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, signp, sizeof(*signp));
5080 return res;
5081}
5082#define INIT_LGAMMAL_R COMMON_INTERCEPT_FUNCTION_LDBL(lgammal_r);
5083#else
5084#define INIT_LGAMMAL_R
5085#endif
5086
5087#if SANITIZER_INTERCEPT_DRAND48_R
5088INTERCEPTOR(int, drand48_r, void *buffer, double *result) {
5089 void *ctx;
5090 COMMON_INTERCEPTOR_ENTER(ctx, drand48_r, buffer, result);
5091 // FIXME: under ASan the call below may write to freed memory and corrupt
5092 // its metadata. See
5093 // https://github.com/google/sanitizers/issues/321.
5094 int res = REAL(drand48_r)(buffer, result);
5095 if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
5096 return res;
5097}
5098INTERCEPTOR(int, lrand48_r, void *buffer, long *result) {
5099 void *ctx;
5100 COMMON_INTERCEPTOR_ENTER(ctx, lrand48_r, buffer, result);
5101 // FIXME: under ASan the call below may write to freed memory and corrupt
5102 // its metadata. See
5103 // https://github.com/google/sanitizers/issues/321.
5104 int res = REAL(lrand48_r)(buffer, result);
5105 if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
5106 return res;
5107}
5108#define INIT_DRAND48_R \
5109 COMMON_INTERCEPT_FUNCTION(drand48_r); \
5110 COMMON_INTERCEPT_FUNCTION(lrand48_r);
5111#else
5112#define INIT_DRAND48_R
5113#endif
5114
5115#if SANITIZER_INTERCEPT_RAND_R
5116INTERCEPTOR(int, rand_r, unsigned *seedp) {
5117 void *ctx;
5118 COMMON_INTERCEPTOR_ENTER(ctx, rand_r, seedp);
5119 COMMON_INTERCEPTOR_READ_RANGE(ctx, seedp, sizeof(*seedp));
5120 return REAL(rand_r)(seedp);
5121}
5122#define INIT_RAND_R COMMON_INTERCEPT_FUNCTION(rand_r);
5123#else
5124#define INIT_RAND_R
5125#endif
5126
5127#if SANITIZER_INTERCEPT_GETLINE
5128INTERCEPTOR(SSIZE_T, getline, char **lineptr, SIZE_T *n, void *stream) {
5129 void *ctx;
5130 COMMON_INTERCEPTOR_ENTER(ctx, getline, lineptr, n, stream);
5131 // FIXME: under ASan the call below may write to freed memory and corrupt
5132 // its metadata. See
5133 // https://github.com/google/sanitizers/issues/321.
5134 SSIZE_T res = REAL(getline)(lineptr, n, stream);
5135 if (res > 0) {
5136 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lineptr, sizeof(*lineptr));
5137 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));
5138 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *lineptr, res + 1);
5139 }
5140 return res;
5141}
5142
5143// FIXME: under ASan the call below may write to freed memory and corrupt its
5144// metadata. See
5145// https://github.com/google/sanitizers/issues/321.
5146#define GETDELIM_INTERCEPTOR_IMPL(vname) \
5147 { \
5148 void *ctx; \
5149 COMMON_INTERCEPTOR_ENTER(ctx, vname, lineptr, n, delim, stream); \
5150 SSIZE_T res = REAL(vname)(lineptr, n, delim, stream); \
5151 if (res > 0) { \
5152 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lineptr, sizeof(*lineptr)); \
5153 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n)); \
5154 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *lineptr, res + 1); \
5155 } \
5156 return res; \
5157 }
5158
5159INTERCEPTOR(SSIZE_T, __getdelim, char **lineptr, SIZE_T *n, int delim,
5160 void *stream)
5161GETDELIM_INTERCEPTOR_IMPL(__getdelim)
5162
5163// There's no __getdelim() on FreeBSD so we supply the getdelim() interceptor
5164// with its own body.
5165INTERCEPTOR(SSIZE_T, getdelim, char **lineptr, SIZE_T *n, int delim,
5166 void *stream)
5167GETDELIM_INTERCEPTOR_IMPL(getdelim)
5168
5169#define INIT_GETLINE \
5170 COMMON_INTERCEPT_FUNCTION(getline); \
5171 COMMON_INTERCEPT_FUNCTION(__getdelim); \
5172 COMMON_INTERCEPT_FUNCTION(getdelim);
5173#else
5174#define INIT_GETLINE
5175#endif
5176
5177#if SANITIZER_INTERCEPT_ICONV
5178INTERCEPTOR(SIZE_T, iconv, void *cd, char **inbuf, SIZE_T *inbytesleft,
5179 char **outbuf, SIZE_T *outbytesleft) {
5180 void *ctx;
5181 COMMON_INTERCEPTOR_ENTER(ctx, iconv, cd, inbuf, inbytesleft, outbuf,
5182 outbytesleft);
5183 if (inbytesleft)
5184 COMMON_INTERCEPTOR_READ_RANGE(ctx, inbytesleft, sizeof(*inbytesleft));
5185 if (inbuf && inbytesleft)
5186 COMMON_INTERCEPTOR_READ_RANGE(ctx, *inbuf, *inbytesleft);
5187 if (outbytesleft)
5188 COMMON_INTERCEPTOR_READ_RANGE(ctx, outbytesleft, sizeof(*outbytesleft));
5189 void *outbuf_orig = outbuf ? *outbuf : nullptr;
5190 // FIXME: under ASan the call below may write to freed memory and corrupt
5191 // its metadata. See
5192 // https://github.com/google/sanitizers/issues/321.
5193 SIZE_T res = REAL(iconv)(cd, inbuf, inbytesleft, outbuf, outbytesleft);
5194 if (outbuf && *outbuf > outbuf_orig) {
5195 SIZE_T sz = (char *)*outbuf - (char *)outbuf_orig;
5196 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, outbuf_orig, sz);
5197 }
5198 return res;
5199}
5200#define INIT_ICONV COMMON_INTERCEPT_FUNCTION(iconv);
5201#else
5202#define INIT_ICONV
5203#endif
5204
5205#if SANITIZER_INTERCEPT_TIMES
5206INTERCEPTOR(__sanitizer_clock_t, times, void *tms) {
5207 void *ctx;
5208 COMMON_INTERCEPTOR_ENTER(ctx, times, tms);
5209 // FIXME: under ASan the call below may write to freed memory and corrupt
5210 // its metadata. See
5211 // https://github.com/google/sanitizers/issues/321.
5212 __sanitizer_clock_t res = REAL(times)(tms);
5213 if (res != (__sanitizer_clock_t)-1 && tms)
5214 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tms, struct_tms_sz);
5215 return res;
5216}
5217#define INIT_TIMES COMMON_INTERCEPT_FUNCTION(times);
5218#else
5219#define INIT_TIMES
5220#endif
5221
5222#if SANITIZER_INTERCEPT_TLS_GET_ADDR
5223#if !SANITIZER_S390
5224#define INIT_TLS_GET_ADDR COMMON_INTERCEPT_FUNCTION(__tls_get_addr)
5225// If you see any crashes around this functions, there are 2 known issues with
5226// it: 1. __tls_get_addr can be called with mis-aligned stack due to:
5227// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58066
5228// 2. It can be called recursively if sanitizer code uses __tls_get_addr
5229// to access thread local variables (it should not happen normally,
5230// because sanitizers use initial-exec tls model).
5231INTERCEPTOR(void *, __tls_get_addr, void *arg) {
5232 void *ctx;
5233 COMMON_INTERCEPTOR_ENTER(ctx, __tls_get_addr, arg);
5234 void *res = REAL(__tls_get_addr)(arg);
5235 uptr tls_begin, tls_end;
5236 COMMON_INTERCEPTOR_GET_TLS_RANGE(&tls_begin, &tls_end);
5237 DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, res, tls_begin, tls_end);
5238 if (dtv) {
5239 // New DTLS block has been allocated.
5240 COMMON_INTERCEPTOR_INITIALIZE_RANGE((void *)dtv->beg, dtv->size);
5241 }
5242 return res;
5243}
5244#if SANITIZER_PPC
5245// On PowerPC, we also need to intercept __tls_get_addr_opt, which has
5246// mostly the same semantics as __tls_get_addr, but its presence enables
5247// some optimizations in linker (which are safe to ignore here).
5248extern "C" __attribute__((alias("__interceptor___tls_get_addr"),
5249 visibility("default")))
5250void *__tls_get_addr_opt(void *arg);
5251#endif
5252#else // SANITIZER_S390
5253// On s390, we have to intercept two functions here:
5254// - __tls_get_addr_internal, which is a glibc-internal function that is like
5255// the usual __tls_get_addr, but returns a TP-relative offset instead of
5256// a proper pointer. It is used by dlsym for TLS symbols.
5257// - __tls_get_offset, which is like the above, but also takes a GOT-relative
5258// descriptor offset as an argument instead of a pointer. GOT address
5259// is passed in r12, so it's necessary to write it in assembly. This is
5260// the function used by the compiler.
5261extern "C" uptr __tls_get_offset_wrapper(void *arg, uptr (*fn)(void *arg));
5262#define INIT_TLS_GET_ADDR COMMON_INTERCEPT_FUNCTION(__tls_get_offset)
5263DEFINE_REAL(uptr, __tls_get_offset, void *arg)
5264extern "C" uptr __tls_get_offset(void *arg);
5265extern "C" uptr __interceptor___tls_get_offset(void *arg);
5266INTERCEPTOR(uptr, __tls_get_addr_internal, void *arg) {
5267 void *ctx;
5268 COMMON_INTERCEPTOR_ENTER(ctx, __tls_get_addr_internal, arg);
5269 uptr res = __tls_get_offset_wrapper(arg, REAL(__tls_get_offset));
5270 uptr tp = reinterpret_cast<uptr>(__builtin_thread_pointer());
5271 void *ptr = reinterpret_cast<void *>(res + tp);
5272 uptr tls_begin, tls_end;
5273 COMMON_INTERCEPTOR_GET_TLS_RANGE(&tls_begin, &tls_end);
5274 DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, ptr, tls_begin, tls_end);
5275 if (dtv) {
5276 // New DTLS block has been allocated.
5277 COMMON_INTERCEPTOR_INITIALIZE_RANGE((void *)dtv->beg, dtv->size);
5278 }
5279 return res;
5280}
5281// We need a hidden symbol aliasing the above, so that we can jump
5282// directly to it from the assembly below.
5283extern "C" __attribute__((alias("__interceptor___tls_get_addr_internal"),
5284 visibility("hidden")))
5285uptr __tls_get_addr_hidden(void *arg);
5286// Now carefully intercept __tls_get_offset.
5287asm(
5288 ".text\n"
5289// The __intercept_ version has to exist, so that gen_dynamic_list.py
5290// exports our symbol.
5291 ".weak __tls_get_offset\n"
5292 ".type __tls_get_offset, @function\n"
5293 "__tls_get_offset:\n"
5294 ".global __interceptor___tls_get_offset\n"
5295 ".type __interceptor___tls_get_offset, @function\n"
5296 "__interceptor___tls_get_offset:\n"
5297#ifdef __s390x__
5298 "la %r2, 0(%r2,%r12)\n"
5299 "jg __tls_get_addr_hidden\n"
5300#else
5301 "basr %r3,0\n"
5302 "0: la %r2,0(%r2,%r12)\n"
5303 "l %r4,1f-0b(%r3)\n"
5304 "b 0(%r4,%r3)\n"
5305 "1: .long __tls_get_addr_hidden - 0b\n"
5306#endif
5307 ".size __interceptor___tls_get_offset, .-__interceptor___tls_get_offset\n"
5308// Assembly wrapper to call REAL(__tls_get_offset)(arg)
5309 ".type __tls_get_offset_wrapper, @function\n"
5310 "__tls_get_offset_wrapper:\n"
5311#ifdef __s390x__
5312 "sgr %r2,%r12\n"
5313#else
5314 "sr %r2,%r12\n"
5315#endif
5316 "br %r3\n"
5317 ".size __tls_get_offset_wrapper, .-__tls_get_offset_wrapper\n"
5318);
5319#endif // SANITIZER_S390
5320#else
5321#define INIT_TLS_GET_ADDR
5322#endif
5323
5324#if SANITIZER_INTERCEPT_LISTXATTR
5325INTERCEPTOR(SSIZE_T, listxattr, const char *path, char *list, SIZE_T size) {
5326 void *ctx;
5327 COMMON_INTERCEPTOR_ENTER(ctx, listxattr, path, list, size);
5328 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
5329 // FIXME: under ASan the call below may write to freed memory and corrupt
5330 // its metadata. See
5331 // https://github.com/google/sanitizers/issues/321.
5332 SSIZE_T res = REAL(listxattr)(path, list, size);
5333 // Here and below, size == 0 is a special case where nothing is written to the
5334 // buffer, and res contains the desired buffer size.
5335 if (size && res > 0 && list) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, list, res);
5336 return res;
5337}
5338INTERCEPTOR(SSIZE_T, llistxattr, const char *path, char *list, SIZE_T size) {
5339 void *ctx;
5340 COMMON_INTERCEPTOR_ENTER(ctx, llistxattr, path, list, size);
5341 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
5342 // FIXME: under ASan the call below may write to freed memory and corrupt
5343 // its metadata. See
5344 // https://github.com/google/sanitizers/issues/321.
5345 SSIZE_T res = REAL(llistxattr)(path, list, size);
5346 if (size && res > 0 && list) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, list, res);
5347 return res;
5348}
5349INTERCEPTOR(SSIZE_T, flistxattr, int fd, char *list, SIZE_T size) {
5350 void *ctx;
5351 COMMON_INTERCEPTOR_ENTER(ctx, flistxattr, fd, list, size);
5352 // FIXME: under ASan the call below may write to freed memory and corrupt
5353 // its metadata. See
5354 // https://github.com/google/sanitizers/issues/321.
5355 SSIZE_T res = REAL(flistxattr)(fd, list, size);
5356 if (size && res > 0 && list) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, list, res);
5357 return res;
5358}
5359#define INIT_LISTXATTR \
5360 COMMON_INTERCEPT_FUNCTION(listxattr); \
5361 COMMON_INTERCEPT_FUNCTION(llistxattr); \
5362 COMMON_INTERCEPT_FUNCTION(flistxattr);
5363#else
5364#define INIT_LISTXATTR
5365#endif
5366
5367#if SANITIZER_INTERCEPT_GETXATTR
5368INTERCEPTOR(SSIZE_T, getxattr, const char *path, const char *name, char *value,
5369 SIZE_T size) {
5370 void *ctx;
5371 COMMON_INTERCEPTOR_ENTER(ctx, getxattr, path, name, value, size);
5372 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
5373 if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
5374 // FIXME: under ASan the call below may write to freed memory and corrupt
5375 // its metadata. See
5376 // https://github.com/google/sanitizers/issues/321.
5377 SSIZE_T res = REAL(getxattr)(path, name, value, size);
5378 if (size && res > 0 && value) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, res);
5379 return res;
5380}
5381INTERCEPTOR(SSIZE_T, lgetxattr, const char *path, const char *name, char *value,
5382 SIZE_T size) {
5383 void *ctx;
5384 COMMON_INTERCEPTOR_ENTER(ctx, lgetxattr, path, name, value, size);
5385 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
5386 if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
5387 // FIXME: under ASan the call below may write to freed memory and corrupt
5388 // its metadata. See
5389 // https://github.com/google/sanitizers/issues/321.
5390 SSIZE_T res = REAL(lgetxattr)(path, name, value, size);
5391 if (size && res > 0 && value) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, res);
5392 return res;
5393}
5394INTERCEPTOR(SSIZE_T, fgetxattr, int fd, const char *name, char *value,
5395 SIZE_T size) {
5396 void *ctx;
5397 COMMON_INTERCEPTOR_ENTER(ctx, fgetxattr, fd, name, value, size);
5398 if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
5399 // FIXME: under ASan the call below may write to freed memory and corrupt
5400 // its metadata. See
5401 // https://github.com/google/sanitizers/issues/321.
5402 SSIZE_T res = REAL(fgetxattr)(fd, name, value, size);
5403 if (size && res > 0 && value) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, res);
5404 return res;
5405}
5406#define INIT_GETXATTR \
5407 COMMON_INTERCEPT_FUNCTION(getxattr); \
5408 COMMON_INTERCEPT_FUNCTION(lgetxattr); \
5409 COMMON_INTERCEPT_FUNCTION(fgetxattr);
5410#else
5411#define INIT_GETXATTR
5412#endif
5413
5414#if SANITIZER_INTERCEPT_GETRESID
5415INTERCEPTOR(int, getresuid, void *ruid, void *euid, void *suid) {
5416 void *ctx;
5417 COMMON_INTERCEPTOR_ENTER(ctx, getresuid, ruid, euid, suid);
5418 // FIXME: under ASan the call below may write to freed memory and corrupt
5419 // its metadata. See
5420 // https://github.com/google/sanitizers/issues/321.
5421 int res = REAL(getresuid)(ruid, euid, suid);
5422 if (res >= 0) {
5423 if (ruid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ruid, uid_t_sz);
5424 if (euid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, euid, uid_t_sz);
5425 if (suid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, suid, uid_t_sz);
5426 }
5427 return res;
5428}
5429INTERCEPTOR(int, getresgid, void *rgid, void *egid, void *sgid) {
5430 void *ctx;
5431 COMMON_INTERCEPTOR_ENTER(ctx, getresgid, rgid, egid, sgid);
5432 // FIXME: under ASan the call below may write to freed memory and corrupt
5433 // its metadata. See
5434 // https://github.com/google/sanitizers/issues/321.
5435 int res = REAL(getresgid)(rgid, egid, sgid);
5436 if (res >= 0) {
5437 if (rgid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rgid, gid_t_sz);
5438 if (egid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, egid, gid_t_sz);
5439 if (sgid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sgid, gid_t_sz);
5440 }
5441 return res;
5442}
5443#define INIT_GETRESID \
5444 COMMON_INTERCEPT_FUNCTION(getresuid); \
5445 COMMON_INTERCEPT_FUNCTION(getresgid);
5446#else
5447#define INIT_GETRESID
5448#endif
5449
5450#if SANITIZER_INTERCEPT_GETIFADDRS
5451// As long as getifaddrs()/freeifaddrs() use calloc()/free(), we don't need to
5452// intercept freeifaddrs(). If that ceases to be the case, we might need to
5453// intercept it to poison the memory again.
5454INTERCEPTOR(int, getifaddrs, __sanitizer_ifaddrs **ifap) {
5455 void *ctx;
5456 COMMON_INTERCEPTOR_ENTER(ctx, getifaddrs, ifap);
5457 // FIXME: under ASan the call below may write to freed memory and corrupt
5458 // its metadata. See
5459 // https://github.com/google/sanitizers/issues/321.
5460 int res = REAL(getifaddrs)(ifap);
5461 if (res == 0 && ifap) {
5462 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifap, sizeof(void *));
5463 __sanitizer_ifaddrs *p = *ifap;
5464 while (p) {
5465 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(__sanitizer_ifaddrs));
5466 if (p->ifa_name)
5467 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_name,
5468 REAL(strlen)(p->ifa_name) + 1);
5469 if (p->ifa_addr)
5470 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_addr, struct_sockaddr_sz);
5471 if (p->ifa_netmask)
5472 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_netmask, struct_sockaddr_sz);
5473 // On Linux this is a union, but the other member also points to a
5474 // struct sockaddr, so the following is sufficient.
5475 if (p->ifa_dstaddr)
5476 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_dstaddr, struct_sockaddr_sz);
5477 // FIXME(smatveev): Unpoison p->ifa_data as well.
5478 p = p->ifa_next;
5479 }
5480 }
5481 return res;
5482}
5483#define INIT_GETIFADDRS \
5484 COMMON_INTERCEPT_FUNCTION(getifaddrs);
5485#else
5486#define INIT_GETIFADDRS
5487#endif
5488
5489#if SANITIZER_INTERCEPT_IF_INDEXTONAME
5490INTERCEPTOR(char *, if_indextoname, unsigned int ifindex, char* ifname) {
5491 void *ctx;
5492 COMMON_INTERCEPTOR_ENTER(ctx, if_indextoname, ifindex, ifname);
5493 // FIXME: under ASan the call below may write to freed memory and corrupt
5494 // its metadata. See
5495 // https://github.com/google/sanitizers/issues/321.
5496 char *res = REAL(if_indextoname)(ifindex, ifname);
5497 if (res && ifname)
5498 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifname, REAL(strlen)(ifname) + 1);
5499 return res;
5500}
5501INTERCEPTOR(unsigned int, if_nametoindex, const char* ifname) {
5502 void *ctx;
5503 COMMON_INTERCEPTOR_ENTER(ctx, if_nametoindex, ifname);
5504 if (ifname)
5505 COMMON_INTERCEPTOR_READ_RANGE(ctx, ifname, REAL(strlen)(ifname) + 1);
5506 return REAL(if_nametoindex)(ifname);
5507}
5508#define INIT_IF_INDEXTONAME \
5509 COMMON_INTERCEPT_FUNCTION(if_indextoname); \
5510 COMMON_INTERCEPT_FUNCTION(if_nametoindex);
5511#else
5512#define INIT_IF_INDEXTONAME
5513#endif
5514
5515#if SANITIZER_INTERCEPT_CAPGET
5516INTERCEPTOR(int, capget, void *hdrp, void *datap) {
5517 void *ctx;
5518 COMMON_INTERCEPTOR_ENTER(ctx, capget, hdrp, datap);
5519 if (hdrp)
5520 COMMON_INTERCEPTOR_READ_RANGE(ctx, hdrp, __user_cap_header_struct_sz);
5521 // FIXME: under ASan the call below may write to freed memory and corrupt
5522 // its metadata. See
5523 // https://github.com/google/sanitizers/issues/321.
5524 int res = REAL(capget)(hdrp, datap);
5525 if (res == 0 && datap)
5526 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, datap, __user_cap_data_struct_sz);
5527 // We can also return -1 and write to hdrp->version if the version passed in
5528 // hdrp->version is unsupported. But that's not a trivial condition to check,
5529 // and anyway COMMON_INTERCEPTOR_READ_RANGE protects us to some extent.
5530 return res;
5531}
5532INTERCEPTOR(int, capset, void *hdrp, const void *datap) {
5533 void *ctx;
5534 COMMON_INTERCEPTOR_ENTER(ctx, capset, hdrp, datap);
5535 if (hdrp)
5536 COMMON_INTERCEPTOR_READ_RANGE(ctx, hdrp, __user_cap_header_struct_sz);
5537 if (datap)
5538 COMMON_INTERCEPTOR_READ_RANGE(ctx, datap, __user_cap_data_struct_sz);
5539 return REAL(capset)(hdrp, datap);
5540}
5541#define INIT_CAPGET \
5542 COMMON_INTERCEPT_FUNCTION(capget); \
5543 COMMON_INTERCEPT_FUNCTION(capset);
5544#else
5545#define INIT_CAPGET
5546#endif
5547
5548#if SANITIZER_INTERCEPT_AEABI_MEM
5549INTERCEPTOR(void *, __aeabi_memmove, void *to, const void *from, uptr size) {
5550 void *ctx;
5551 COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
5552}
5553
5554INTERCEPTOR(void *, __aeabi_memmove4, void *to, const void *from, uptr size) {
5555 void *ctx;
5556 COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
5557}
5558
5559INTERCEPTOR(void *, __aeabi_memmove8, void *to, const void *from, uptr size) {
5560 void *ctx;
5561 COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
5562}
5563
5564INTERCEPTOR(void *, __aeabi_memcpy, void *to, const void *from, uptr size) {
5565 void *ctx;
5566 COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
5567}
5568
5569INTERCEPTOR(void *, __aeabi_memcpy4, void *to, const void *from, uptr size) {
5570 void *ctx;
5571 COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
5572}
5573
5574INTERCEPTOR(void *, __aeabi_memcpy8, void *to, const void *from, uptr size) {
5575 void *ctx;
5576 COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
5577}
5578
5579// Note the argument order.
5580INTERCEPTOR(void *, __aeabi_memset, void *block, uptr size, int c) {
5581 void *ctx;
5582 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
5583}
5584
5585INTERCEPTOR(void *, __aeabi_memset4, void *block, uptr size, int c) {
5586 void *ctx;
5587 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
5588}
5589
5590INTERCEPTOR(void *, __aeabi_memset8, void *block, uptr size, int c) {
5591 void *ctx;
5592 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
5593}
5594
5595INTERCEPTOR(void *, __aeabi_memclr, void *block, uptr size) {
5596 void *ctx;
5597 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
5598}
5599
5600INTERCEPTOR(void *, __aeabi_memclr4, void *block, uptr size) {
5601 void *ctx;
5602 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
5603}
5604
5605INTERCEPTOR(void *, __aeabi_memclr8, void *block, uptr size) {
5606 void *ctx;
5607 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
5608}
5609
5610#define INIT_AEABI_MEM \
5611 COMMON_INTERCEPT_FUNCTION(__aeabi_memmove); \
5612 COMMON_INTERCEPT_FUNCTION(__aeabi_memmove4); \
5613 COMMON_INTERCEPT_FUNCTION(__aeabi_memmove8); \
5614 COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy); \
5615 COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy4); \
5616 COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy8); \
5617 COMMON_INTERCEPT_FUNCTION(__aeabi_memset); \
5618 COMMON_INTERCEPT_FUNCTION(__aeabi_memset4); \
5619 COMMON_INTERCEPT_FUNCTION(__aeabi_memset8); \
5620 COMMON_INTERCEPT_FUNCTION(__aeabi_memclr); \
5621 COMMON_INTERCEPT_FUNCTION(__aeabi_memclr4); \
5622 COMMON_INTERCEPT_FUNCTION(__aeabi_memclr8);
5623#else
5624#define INIT_AEABI_MEM
5625#endif // SANITIZER_INTERCEPT_AEABI_MEM
5626
5627#if SANITIZER_INTERCEPT___BZERO
5628INTERCEPTOR(void *, __bzero, void *block, uptr size) {
5629 void *ctx;
5630 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
5631}
5632#define INIT___BZERO COMMON_INTERCEPT_FUNCTION(__bzero);
5633#else
5634#define INIT___BZERO
5635#endif // SANITIZER_INTERCEPT___BZERO
5636
5637#if SANITIZER_INTERCEPT_BZERO
5638INTERCEPTOR(void *, bzero, void *block, uptr size) {
5639 void *ctx;
5640 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
5641}
5642#define INIT_BZERO COMMON_INTERCEPT_FUNCTION(bzero);
5643#else
5644#define INIT_BZERO
5645#endif // SANITIZER_INTERCEPT_BZERO
5646
5647#if SANITIZER_INTERCEPT_FTIME
5648INTERCEPTOR(int, ftime, __sanitizer_timeb *tp) {
5649 void *ctx;
5650 COMMON_INTERCEPTOR_ENTER(ctx, ftime, tp);
5651 // FIXME: under ASan the call below may write to freed memory and corrupt
5652 // its metadata. See
5653 // https://github.com/google/sanitizers/issues/321.
5654 int res = REAL(ftime)(tp);
5655 if (tp)
5656 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, sizeof(*tp));
5657 return res;
5658}
5659#define INIT_FTIME COMMON_INTERCEPT_FUNCTION(ftime);
5660#else
5661#define INIT_FTIME
5662#endif // SANITIZER_INTERCEPT_FTIME
5663
5664#if SANITIZER_INTERCEPT_XDR
5665INTERCEPTOR(void, xdrmem_create, __sanitizer_XDR *xdrs, uptr addr,
5666 unsigned size, int op) {
5667 void *ctx;
5668 COMMON_INTERCEPTOR_ENTER(ctx, xdrmem_create, xdrs, addr, size, op);
5669 // FIXME: under ASan the call below may write to freed memory and corrupt
5670 // its metadata. See
5671 // https://github.com/google/sanitizers/issues/321.
5672 REAL(xdrmem_create)(xdrs, addr, size, op);
5673 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, xdrs, sizeof(*xdrs));
5674 if (op == __sanitizer_XDR_ENCODE) {
5675 // It's not obvious how much data individual xdr_ routines write.
5676 // Simply unpoison the entire target buffer in advance.
5677 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (void *)addr, size);
5678 }
5679}
5680
5681INTERCEPTOR(void, xdrstdio_create, __sanitizer_XDR *xdrs, void *file, int op) {
5682 void *ctx;
5683 COMMON_INTERCEPTOR_ENTER(ctx, xdrstdio_create, xdrs, file, op);
5684 // FIXME: under ASan the call below may write to freed memory and corrupt
5685 // its metadata. See
5686 // https://github.com/google/sanitizers/issues/321.
5687 REAL(xdrstdio_create)(xdrs, file, op);
5688 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, xdrs, sizeof(*xdrs));
5689}
5690
5691// FIXME: under ASan the call below may write to freed memory and corrupt
5692// its metadata. See
5693// https://github.com/google/sanitizers/issues/321.
5694#define XDR_INTERCEPTOR(F, T) \
5695 INTERCEPTOR(int, F, __sanitizer_XDR *xdrs, T *p) { \
5696 void *ctx; \
5697 COMMON_INTERCEPTOR_ENTER(ctx, F, xdrs, p); \
5698 if (p && xdrs->x_op == __sanitizer_XDR_ENCODE) \
5699 COMMON_INTERCEPTOR_READ_RANGE(ctx, p, sizeof(*p)); \
5700 int res = REAL(F)(xdrs, p); \
5701 if (res && p && xdrs->x_op == __sanitizer_XDR_DECODE) \
5702 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p)); \
5703 return res; \
5704 }
5705
5706XDR_INTERCEPTOR(xdr_short, short)
5707XDR_INTERCEPTOR(xdr_u_short, unsigned short)
5708XDR_INTERCEPTOR(xdr_int, int)
5709XDR_INTERCEPTOR(xdr_u_int, unsigned)
5710XDR_INTERCEPTOR(xdr_long, long)
5711XDR_INTERCEPTOR(xdr_u_long, unsigned long)
5712XDR_INTERCEPTOR(xdr_hyper, long long)
5713XDR_INTERCEPTOR(xdr_u_hyper, unsigned long long)
5714XDR_INTERCEPTOR(xdr_longlong_t, long long)
5715XDR_INTERCEPTOR(xdr_u_longlong_t, unsigned long long)
5716XDR_INTERCEPTOR(xdr_int8_t, u8)
5717XDR_INTERCEPTOR(xdr_uint8_t, u8)
5718XDR_INTERCEPTOR(xdr_int16_t, u16)
5719XDR_INTERCEPTOR(xdr_uint16_t, u16)
5720XDR_INTERCEPTOR(xdr_int32_t, u32)
5721XDR_INTERCEPTOR(xdr_uint32_t, u32)
5722XDR_INTERCEPTOR(xdr_int64_t, u64)
5723XDR_INTERCEPTOR(xdr_uint64_t, u64)
5724XDR_INTERCEPTOR(xdr_quad_t, long long)
5725XDR_INTERCEPTOR(xdr_u_quad_t, unsigned long long)
5726XDR_INTERCEPTOR(xdr_bool, bool)
5727XDR_INTERCEPTOR(xdr_enum, int)
5728XDR_INTERCEPTOR(xdr_char, char)
5729XDR_INTERCEPTOR(xdr_u_char, unsigned char)
5730XDR_INTERCEPTOR(xdr_float, float)
5731XDR_INTERCEPTOR(xdr_double, double)
5732
5733// FIXME: intercept xdr_array, opaque, union, vector, reference, pointer,
5734// wrapstring, sizeof
5735
5736INTERCEPTOR(int, xdr_bytes, __sanitizer_XDR *xdrs, char **p, unsigned *sizep,
5737 unsigned maxsize) {
5738 void *ctx;
5739 COMMON_INTERCEPTOR_ENTER(ctx, xdr_bytes, xdrs, p, sizep, maxsize);
5740 if (p && sizep && xdrs->x_op == __sanitizer_XDR_ENCODE) {
5741 COMMON_INTERCEPTOR_READ_RANGE(ctx, p, sizeof(*p));
5742 COMMON_INTERCEPTOR_READ_RANGE(ctx, sizep, sizeof(*sizep));
5743 COMMON_INTERCEPTOR_READ_RANGE(ctx, *p, *sizep);
5744 }
5745 // FIXME: under ASan the call below may write to freed memory and corrupt
5746 // its metadata. See
5747 // https://github.com/google/sanitizers/issues/321.
5748 int res = REAL(xdr_bytes)(xdrs, p, sizep, maxsize);
5749 if (p && sizep && xdrs->x_op == __sanitizer_XDR_DECODE) {
5750 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
5751 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sizep, sizeof(*sizep));
5752 if (res && *p && *sizep) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, *sizep);
5753 }
5754 return res;
5755}
5756
5757INTERCEPTOR(int, xdr_string, __sanitizer_XDR *xdrs, char **p,
5758 unsigned maxsize) {
5759 void *ctx;
5760 COMMON_INTERCEPTOR_ENTER(ctx, xdr_string, xdrs, p, maxsize);
5761 if (p && xdrs->x_op == __sanitizer_XDR_ENCODE) {
5762 COMMON_INTERCEPTOR_READ_RANGE(ctx, p, sizeof(*p));
5763 COMMON_INTERCEPTOR_READ_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
5764 }
5765 // FIXME: under ASan the call below may write to freed memory and corrupt
5766 // its metadata. See
5767 // https://github.com/google/sanitizers/issues/321.
5768 int res = REAL(xdr_string)(xdrs, p, maxsize);
5769 if (p && xdrs->x_op == __sanitizer_XDR_DECODE) {
5770 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
5771 if (res && *p)
5772 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
5773 }
5774 return res;
5775}
5776
5777#define INIT_XDR \
5778 COMMON_INTERCEPT_FUNCTION(xdrmem_create); \
5779 COMMON_INTERCEPT_FUNCTION(xdrstdio_create); \
5780 COMMON_INTERCEPT_FUNCTION(xdr_short); \
5781 COMMON_INTERCEPT_FUNCTION(xdr_u_short); \
5782 COMMON_INTERCEPT_FUNCTION(xdr_int); \
5783 COMMON_INTERCEPT_FUNCTION(xdr_u_int); \
5784 COMMON_INTERCEPT_FUNCTION(xdr_long); \
5785 COMMON_INTERCEPT_FUNCTION(xdr_u_long); \
5786 COMMON_INTERCEPT_FUNCTION(xdr_hyper); \
5787 COMMON_INTERCEPT_FUNCTION(xdr_u_hyper); \
5788 COMMON_INTERCEPT_FUNCTION(xdr_longlong_t); \
5789 COMMON_INTERCEPT_FUNCTION(xdr_u_longlong_t); \
5790 COMMON_INTERCEPT_FUNCTION(xdr_int8_t); \
5791 COMMON_INTERCEPT_FUNCTION(xdr_uint8_t); \
5792 COMMON_INTERCEPT_FUNCTION(xdr_int16_t); \
5793 COMMON_INTERCEPT_FUNCTION(xdr_uint16_t); \
5794 COMMON_INTERCEPT_FUNCTION(xdr_int32_t); \
5795 COMMON_INTERCEPT_FUNCTION(xdr_uint32_t); \
5796 COMMON_INTERCEPT_FUNCTION(xdr_int64_t); \
5797 COMMON_INTERCEPT_FUNCTION(xdr_uint64_t); \
5798 COMMON_INTERCEPT_FUNCTION(xdr_quad_t); \
5799 COMMON_INTERCEPT_FUNCTION(xdr_u_quad_t); \
5800 COMMON_INTERCEPT_FUNCTION(xdr_bool); \
5801 COMMON_INTERCEPT_FUNCTION(xdr_enum); \
5802 COMMON_INTERCEPT_FUNCTION(xdr_char); \
5803 COMMON_INTERCEPT_FUNCTION(xdr_u_char); \
5804 COMMON_INTERCEPT_FUNCTION(xdr_float); \
5805 COMMON_INTERCEPT_FUNCTION(xdr_double); \
5806 COMMON_INTERCEPT_FUNCTION(xdr_bytes); \
5807 COMMON_INTERCEPT_FUNCTION(xdr_string);
5808#else
5809#define INIT_XDR
5810#endif // SANITIZER_INTERCEPT_XDR
5811
5812#if SANITIZER_INTERCEPT_TSEARCH
5813INTERCEPTOR(void *, tsearch, void *key, void **rootp,
5814 int (*compar)(const void *, const void *)) {
5815 void *ctx;
5816 COMMON_INTERCEPTOR_ENTER(ctx, tsearch, key, rootp, compar);
5817 // FIXME: under ASan the call below may write to freed memory and corrupt
5818 // its metadata. See
5819 // https://github.com/google/sanitizers/issues/321.
5820 void *res = REAL(tsearch)(key, rootp, compar);
5821 if (res && *(void **)res == key)
5822 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, sizeof(void *));
5823 return res;
5824}
5825#define INIT_TSEARCH COMMON_INTERCEPT_FUNCTION(tsearch);
5826#else
5827#define INIT_TSEARCH
5828#endif
5829
5830#if SANITIZER_INTERCEPT_LIBIO_INTERNALS || SANITIZER_INTERCEPT_FOPEN || \
5831 SANITIZER_INTERCEPT_OPEN_MEMSTREAM
5832void unpoison_file(__sanitizer_FILE *fp) {
5833#if SANITIZER_HAS_STRUCT_FILE
5834 COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp, sizeof(*fp));
5835#if SANITIZER_NETBSD
5836 if (fp->_bf._base && fp->_bf._size > 0)
5837 COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp->_bf._base,
5838 fp->_bf._size);
5839#else
5840 if (fp->_IO_read_base && fp->_IO_read_base < fp->_IO_read_end)
5841 COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp->_IO_read_base,
5842 fp->_IO_read_end - fp->_IO_read_base);
5843#endif
5844#endif // SANITIZER_HAS_STRUCT_FILE
5845}
5846#endif
5847
5848#if SANITIZER_INTERCEPT_LIBIO_INTERNALS
5849// These guys are called when a .c source is built with -O2.
5850INTERCEPTOR(int, __uflow, __sanitizer_FILE *fp) {
5851 void *ctx;
5852 COMMON_INTERCEPTOR_ENTER(ctx, __uflow, fp);
5853 int res = REAL(__uflow)(fp);
5854 unpoison_file(fp);
5855 return res;
5856}
5857INTERCEPTOR(int, __underflow, __sanitizer_FILE *fp) {
5858 void *ctx;
5859 COMMON_INTERCEPTOR_ENTER(ctx, __underflow, fp);
5860 int res = REAL(__underflow)(fp);
5861 unpoison_file(fp);
5862 return res;
5863}
5864INTERCEPTOR(int, __overflow, __sanitizer_FILE *fp, int ch) {
5865 void *ctx;
5866 COMMON_INTERCEPTOR_ENTER(ctx, __overflow, fp, ch);
5867 int res = REAL(__overflow)(fp, ch);
5868 unpoison_file(fp);
5869 return res;
5870}
5871INTERCEPTOR(int, __wuflow, __sanitizer_FILE *fp) {
5872 void *ctx;
5873 COMMON_INTERCEPTOR_ENTER(ctx, __wuflow, fp);
5874 int res = REAL(__wuflow)(fp);
5875 unpoison_file(fp);
5876 return res;
5877}
5878INTERCEPTOR(int, __wunderflow, __sanitizer_FILE *fp) {
5879 void *ctx;
5880 COMMON_INTERCEPTOR_ENTER(ctx, __wunderflow, fp);
5881 int res = REAL(__wunderflow)(fp);
5882 unpoison_file(fp);
5883 return res;
5884}
5885INTERCEPTOR(int, __woverflow, __sanitizer_FILE *fp, int ch) {
5886 void *ctx;
5887 COMMON_INTERCEPTOR_ENTER(ctx, __woverflow, fp, ch);
5888 int res = REAL(__woverflow)(fp, ch);
5889 unpoison_file(fp);
5890 return res;
5891}
5892#define INIT_LIBIO_INTERNALS \
5893 COMMON_INTERCEPT_FUNCTION(__uflow); \
5894 COMMON_INTERCEPT_FUNCTION(__underflow); \
5895 COMMON_INTERCEPT_FUNCTION(__overflow); \
5896 COMMON_INTERCEPT_FUNCTION(__wuflow); \
5897 COMMON_INTERCEPT_FUNCTION(__wunderflow); \
5898 COMMON_INTERCEPT_FUNCTION(__woverflow);
5899#else
5900#define INIT_LIBIO_INTERNALS
5901#endif
5902
5903#if SANITIZER_INTERCEPT_FOPEN
5904INTERCEPTOR(__sanitizer_FILE *, fopen, const char *path, const char *mode) {
5905 void *ctx;
5906 COMMON_INTERCEPTOR_ENTER(ctx, fopen, path, mode);
5907 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
5908 COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
5909 __sanitizer_FILE *res = REAL(fopen)(path, mode);
5910 COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
5911 if (res) unpoison_file(res);
5912 return res;
5913}
5914INTERCEPTOR(__sanitizer_FILE *, fdopen, int fd, const char *mode) {
5915 void *ctx;
5916 COMMON_INTERCEPTOR_ENTER(ctx, fdopen, fd, mode);
5917 COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
5918 __sanitizer_FILE *res = REAL(fdopen)(fd, mode);
5919 if (res) unpoison_file(res);
5920 return res;
5921}
5922INTERCEPTOR(__sanitizer_FILE *, freopen, const char *path, const char *mode,
5923 __sanitizer_FILE *fp) {
5924 void *ctx;
5925 COMMON_INTERCEPTOR_ENTER(ctx, freopen, path, mode, fp);
5926 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
5927 COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
5928 COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
5929 __sanitizer_FILE *res = REAL(freopen)(path, mode, fp);
5930 COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
5931 if (res) unpoison_file(res);
5932 return res;
5933}
5934#define INIT_FOPEN \
5935 COMMON_INTERCEPT_FUNCTION(fopen); \
5936 COMMON_INTERCEPT_FUNCTION(fdopen); \
5937 COMMON_INTERCEPT_FUNCTION(freopen);
5938#else
5939#define INIT_FOPEN
5940#endif
5941
5942#if SANITIZER_INTERCEPT_FOPEN64
5943INTERCEPTOR(__sanitizer_FILE *, fopen64, const char *path, const char *mode) {
5944 void *ctx;
5945 COMMON_INTERCEPTOR_ENTER(ctx, fopen64, path, mode);
5946 COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
5947 COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
5948 __sanitizer_FILE *res = REAL(fopen64)(path, mode);
5949 COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
5950 if (res) unpoison_file(res);
5951 return res;
5952}
5953INTERCEPTOR(__sanitizer_FILE *, freopen64, const char *path, const char *mode,
5954 __sanitizer_FILE *fp) {
5955 void *ctx;
5956 COMMON_INTERCEPTOR_ENTER(ctx, freopen64, path, mode, fp);
5957 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
5958 COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
5959 COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
5960 __sanitizer_FILE *res = REAL(freopen64)(path, mode, fp);
5961 COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
5962 if (res) unpoison_file(res);
5963 return res;
5964}
5965#define INIT_FOPEN64 \
5966 COMMON_INTERCEPT_FUNCTION(fopen64); \
5967 COMMON_INTERCEPT_FUNCTION(freopen64);
5968#else
5969#define INIT_FOPEN64
5970#endif
5971
5972#if SANITIZER_INTERCEPT_OPEN_MEMSTREAM
5973INTERCEPTOR(__sanitizer_FILE *, open_memstream, char **ptr, SIZE_T *sizeloc) {
5974 void *ctx;
5975 COMMON_INTERCEPTOR_ENTER(ctx, open_memstream, ptr, sizeloc);
5976 // FIXME: under ASan the call below may write to freed memory and corrupt
5977 // its metadata. See
5978 // https://github.com/google/sanitizers/issues/321.
5979 __sanitizer_FILE *res = REAL(open_memstream)(ptr, sizeloc);
5980 if (res) {
5981 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, sizeof(*ptr));
5982 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sizeloc, sizeof(*sizeloc));
5983 unpoison_file(res);
5984 FileMetadata file = {ptr, sizeloc};
5985 SetInterceptorMetadata(res, file);
5986 }
5987 return res;
5988}
5989INTERCEPTOR(__sanitizer_FILE *, open_wmemstream, wchar_t **ptr,
5990 SIZE_T *sizeloc) {
5991 void *ctx;
5992 COMMON_INTERCEPTOR_ENTER(ctx, open_wmemstream, ptr, sizeloc);
5993 __sanitizer_FILE *res = REAL(open_wmemstream)(ptr, sizeloc);
5994 if (res) {
5995 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, sizeof(*ptr));
5996 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sizeloc, sizeof(*sizeloc));
5997 unpoison_file(res);
5998 FileMetadata file = {(char **)ptr, sizeloc};
5999 SetInterceptorMetadata(res, file);
6000 }
6001 return res;
6002}
6003INTERCEPTOR(__sanitizer_FILE *, fmemopen, void *buf, SIZE_T size,
6004 const char *mode) {
6005 void *ctx;
6006 COMMON_INTERCEPTOR_ENTER(ctx, fmemopen, buf, size, mode);
6007 // FIXME: under ASan the call below may write to freed memory and corrupt
6008 // its metadata. See
6009 // https://github.com/google/sanitizers/issues/321.
6010 __sanitizer_FILE *res = REAL(fmemopen)(buf, size, mode);
6011 if (res) unpoison_file(res);
6012 return res;
6013}
6014#define INIT_OPEN_MEMSTREAM \
6015 COMMON_INTERCEPT_FUNCTION(open_memstream); \
6016 COMMON_INTERCEPT_FUNCTION(open_wmemstream); \
6017 COMMON_INTERCEPT_FUNCTION(fmemopen);
6018#else
6019#define INIT_OPEN_MEMSTREAM
6020#endif
6021
6022#if SANITIZER_INTERCEPT_OBSTACK
6023static void initialize_obstack(__sanitizer_obstack *obstack) {
6024 COMMON_INTERCEPTOR_INITIALIZE_RANGE(obstack, sizeof(*obstack));
6025 if (obstack->chunk)
6026 COMMON_INTERCEPTOR_INITIALIZE_RANGE(obstack->chunk,
6027 sizeof(*obstack->chunk));
6028}
6029
6030INTERCEPTOR(int, _obstack_begin_1, __sanitizer_obstack *obstack, int sz,
6031 int align, void *(*alloc_fn)(uptr arg, uptr sz),
6032 void (*free_fn)(uptr arg, void *p)) {
6033 void *ctx;
6034 COMMON_INTERCEPTOR_ENTER(ctx, _obstack_begin_1, obstack, sz, align, alloc_fn,
6035 free_fn);
6036 int res = REAL(_obstack_begin_1)(obstack, sz, align, alloc_fn, free_fn);
6037 if (res) initialize_obstack(obstack);
6038 return res;
6039}
6040INTERCEPTOR(int, _obstack_begin, __sanitizer_obstack *obstack, int sz,
6041 int align, void *(*alloc_fn)(uptr sz), void (*free_fn)(void *p)) {
6042 void *ctx;
6043 COMMON_INTERCEPTOR_ENTER(ctx, _obstack_begin, obstack, sz, align, alloc_fn,
6044 free_fn);
6045 int res = REAL(_obstack_begin)(obstack, sz, align, alloc_fn, free_fn);
6046 if (res) initialize_obstack(obstack);
6047 return res;
6048}
6049INTERCEPTOR(void, _obstack_newchunk, __sanitizer_obstack *obstack, int length) {
6050 void *ctx;
6051 COMMON_INTERCEPTOR_ENTER(ctx, _obstack_newchunk, obstack, length);
6052 REAL(_obstack_newchunk)(obstack, length);
6053 if (obstack->chunk)
6054 COMMON_INTERCEPTOR_INITIALIZE_RANGE(
6055 obstack->chunk, obstack->next_free - (char *)obstack->chunk);
6056}
6057#define INIT_OBSTACK \
6058 COMMON_INTERCEPT_FUNCTION(_obstack_begin_1); \
6059 COMMON_INTERCEPT_FUNCTION(_obstack_begin); \
6060 COMMON_INTERCEPT_FUNCTION(_obstack_newchunk);
6061#else
6062#define INIT_OBSTACK
6063#endif
6064
6065#if SANITIZER_INTERCEPT_FFLUSH
6066INTERCEPTOR(int, fflush, __sanitizer_FILE *fp) {
6067 void *ctx;
6068 COMMON_INTERCEPTOR_ENTER(ctx, fflush, fp);
6069 int res = REAL(fflush)(fp);
6070 // FIXME: handle fp == NULL
6071 if (fp) {
6072 const FileMetadata *m = GetInterceptorMetadata(fp);
6073 if (m) COMMON_INTERCEPTOR_INITIALIZE_RANGE(*m->addr, *m->size);
6074 }
6075 return res;
6076}
6077#define INIT_FFLUSH COMMON_INTERCEPT_FUNCTION(fflush);
6078#else
6079#define INIT_FFLUSH
6080#endif
6081
6082#if SANITIZER_INTERCEPT_FCLOSE
6083INTERCEPTOR(int, fclose, __sanitizer_FILE *fp) {
6084 void *ctx;
6085 COMMON_INTERCEPTOR_ENTER(ctx, fclose, fp);
6086 COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
6087 const FileMetadata *m = GetInterceptorMetadata(fp);
6088 int res = REAL(fclose)(fp);
6089 if (m) {
6090 COMMON_INTERCEPTOR_INITIALIZE_RANGE(*m->addr, *m->size);
6091 DeleteInterceptorMetadata(fp);
6092 }
6093 return res;
6094}
6095#define INIT_FCLOSE COMMON_INTERCEPT_FUNCTION(fclose);
6096#else
6097#define INIT_FCLOSE
6098#endif
6099
6100#if SANITIZER_INTERCEPT_DLOPEN_DLCLOSE
6101INTERCEPTOR(void*, dlopen, const char *filename, int flag) {
6102 void *ctx;
6103 COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, dlopen, filename, flag);
6104 if (filename) COMMON_INTERCEPTOR_READ_STRING(ctx, filename, 0);
6105 COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag);
6106 void *res = REAL(dlopen)(filename, flag);
6107 Symbolizer::GetOrInit()->InvalidateModuleList();
6108 COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, res);
6109 return res;
6110}
6111
6112INTERCEPTOR(int, dlclose, void *handle) {
6113 void *ctx;
6114 COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, dlclose, handle);
6115 int res = REAL(dlclose)(handle);
6116 Symbolizer::GetOrInit()->InvalidateModuleList();
6117 COMMON_INTERCEPTOR_LIBRARY_UNLOADED();
6118 return res;
6119}
6120#define INIT_DLOPEN_DLCLOSE \
6121 COMMON_INTERCEPT_FUNCTION(dlopen); \
6122 COMMON_INTERCEPT_FUNCTION(dlclose);
6123#else
6124#define INIT_DLOPEN_DLCLOSE
6125#endif
6126
6127#if SANITIZER_INTERCEPT_GETPASS
6128INTERCEPTOR(char *, getpass, const char *prompt) {
6129 void *ctx;
6130 COMMON_INTERCEPTOR_ENTER(ctx, getpass, prompt);
6131 if (prompt)
6132 COMMON_INTERCEPTOR_READ_RANGE(ctx, prompt, REAL(strlen)(prompt)+1);
6133 char *res = REAL(getpass)(prompt);
6134 if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res)+1);
6135 return res;
6136}
6137
6138#define INIT_GETPASS COMMON_INTERCEPT_FUNCTION(getpass);
6139#else
6140#define INIT_GETPASS
6141#endif
6142
6143#if SANITIZER_INTERCEPT_TIMERFD
6144INTERCEPTOR(int, timerfd_settime, int fd, int flags, void *new_value,
6145 void *old_value) {
6146 void *ctx;
6147 COMMON_INTERCEPTOR_ENTER(ctx, timerfd_settime, fd, flags, new_value,
6148 old_value);
6149 COMMON_INTERCEPTOR_READ_RANGE(ctx, new_value, struct_itimerspec_sz);
6150 int res = REAL(timerfd_settime)(fd, flags, new_value, old_value);
6151 if (res != -1 && old_value)
6152 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, old_value, struct_itimerspec_sz);
6153 return res;
6154}
6155
6156INTERCEPTOR(int, timerfd_gettime, int fd, void *curr_value) {
6157 void *ctx;
6158 COMMON_INTERCEPTOR_ENTER(ctx, timerfd_gettime, fd, curr_value);
6159 int res = REAL(timerfd_gettime)(fd, curr_value);
6160 if (res != -1 && curr_value)
6161 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, curr_value, struct_itimerspec_sz);
6162 return res;
6163}
6164#define INIT_TIMERFD \
6165 COMMON_INTERCEPT_FUNCTION(timerfd_settime); \
6166 COMMON_INTERCEPT_FUNCTION(timerfd_gettime);
6167#else
6168#define INIT_TIMERFD
6169#endif
6170
6171#if SANITIZER_INTERCEPT_MLOCKX
6172// Linux kernel has a bug that leads to kernel deadlock if a process
6173// maps TBs of memory and then calls mlock().
6174static void MlockIsUnsupported() {
6175 static atomic_uint8_t printed;
6176 if (atomic_exchange(&printed, 1, memory_order_relaxed))
6177 return;
6178 VPrintf(1, "%s ignores mlock/mlockall/munlock/munlockall\n",
6179 SanitizerToolName);
6180}
6181
6182INTERCEPTOR(int, mlock, const void *addr, uptr len) {
6183 MlockIsUnsupported();
6184 return 0;
6185}
6186
6187INTERCEPTOR(int, munlock, const void *addr, uptr len) {
6188 MlockIsUnsupported();
6189 return 0;
6190}
6191
6192INTERCEPTOR(int, mlockall, int flags) {
6193 MlockIsUnsupported();
6194 return 0;
6195}
6196
6197INTERCEPTOR(int, munlockall, void) {
6198 MlockIsUnsupported();
6199 return 0;
6200}
6201
6202#define INIT_MLOCKX \
6203 COMMON_INTERCEPT_FUNCTION(mlock); \
6204 COMMON_INTERCEPT_FUNCTION(munlock); \
6205 COMMON_INTERCEPT_FUNCTION(mlockall); \
6206 COMMON_INTERCEPT_FUNCTION(munlockall);
6207
6208#else
6209#define INIT_MLOCKX
6210#endif // SANITIZER_INTERCEPT_MLOCKX
6211
6212#if SANITIZER_INTERCEPT_FOPENCOOKIE
6213struct WrappedCookie {
6214 void *real_cookie;
6215 __sanitizer_cookie_io_functions_t real_io_funcs;
6216};
6217
6218static uptr wrapped_read(void *cookie, char *buf, uptr size) {
6219 COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
6220 WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie;
6221 __sanitizer_cookie_io_read real_read = wrapped_cookie->real_io_funcs.read;
6222 return real_read ? real_read(wrapped_cookie->real_cookie, buf, size) : 0;
6223}
6224
6225static uptr wrapped_write(void *cookie, const char *buf, uptr size) {
6226 COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
6227 WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie;
6228 __sanitizer_cookie_io_write real_write = wrapped_cookie->real_io_funcs.write;
6229 return real_write ? real_write(wrapped_cookie->real_cookie, buf, size) : size;
6230}
6231
6232static int wrapped_seek(void *cookie, u64 *offset, int whence) {
6233 COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
6234 COMMON_INTERCEPTOR_INITIALIZE_RANGE(offset, sizeof(*offset));
6235 WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie;
6236 __sanitizer_cookie_io_seek real_seek = wrapped_cookie->real_io_funcs.seek;
6237 return real_seek ? real_seek(wrapped_cookie->real_cookie, offset, whence)
6238 : -1;
6239}
6240
6241static int wrapped_close(void *cookie) {
6242 COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
6243 WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie;
6244 __sanitizer_cookie_io_close real_close = wrapped_cookie->real_io_funcs.close;
6245 int res = real_close ? real_close(wrapped_cookie->real_cookie) : 0;
6246 InternalFree(wrapped_cookie);
6247 return res;
6248}
6249
6250INTERCEPTOR(__sanitizer_FILE *, fopencookie, void *cookie, const char *mode,
6251 __sanitizer_cookie_io_functions_t io_funcs) {
6252 void *ctx;
6253 COMMON_INTERCEPTOR_ENTER(ctx, fopencookie, cookie, mode, io_funcs);
6254 WrappedCookie *wrapped_cookie =
6255 (WrappedCookie *)InternalAlloc(sizeof(WrappedCookie));
6256 wrapped_cookie->real_cookie = cookie;
6257 wrapped_cookie->real_io_funcs = io_funcs;
6258 __sanitizer_FILE *res =
6259 REAL(fopencookie)(wrapped_cookie, mode, {wrapped_read, wrapped_write,
6260 wrapped_seek, wrapped_close});
6261 return res;
6262}
6263
6264#define INIT_FOPENCOOKIE COMMON_INTERCEPT_FUNCTION(fopencookie);
6265#else
6266#define INIT_FOPENCOOKIE
6267#endif // SANITIZER_INTERCEPT_FOPENCOOKIE
6268
6269#if SANITIZER_INTERCEPT_SEM
6270INTERCEPTOR(int, sem_init, __sanitizer_sem_t *s, int pshared, unsigned value) {
6271 void *ctx;
6272 COMMON_INTERCEPTOR_ENTER(ctx, sem_init, s, pshared, value);
6273 // Workaround a bug in glibc's "old" semaphore implementation by
6274 // zero-initializing the sem_t contents. This has to be done here because
6275 // interceptors bind to the lowest symbols version by default, hitting the
6276 // buggy code path while the non-sanitized build of the same code works fine.
6277 REAL(memset)(s, 0, sizeof(*s));
6278 int res = REAL(sem_init)(s, pshared, value);
6279 return res;
6280}
6281
6282INTERCEPTOR(int, sem_destroy, __sanitizer_sem_t *s) {
6283 void *ctx;
6284 COMMON_INTERCEPTOR_ENTER(ctx, sem_destroy, s);
6285 int res = REAL(sem_destroy)(s);
6286 return res;
6287}
6288
6289INTERCEPTOR(int, sem_wait, __sanitizer_sem_t *s) {
6290 void *ctx;
6291 COMMON_INTERCEPTOR_ENTER(ctx, sem_wait, s);
6292 int res = COMMON_INTERCEPTOR_BLOCK_REAL(sem_wait)(s);
6293 if (res == 0) {
6294 COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s);
6295 }
6296 return res;
6297}
6298
6299INTERCEPTOR(int, sem_trywait, __sanitizer_sem_t *s) {
6300 void *ctx;
6301 COMMON_INTERCEPTOR_ENTER(ctx, sem_trywait, s);
6302 int res = COMMON_INTERCEPTOR_BLOCK_REAL(sem_trywait)(s);
6303 if (res == 0) {
6304 COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s);
6305 }
6306 return res;
6307}
6308
6309INTERCEPTOR(int, sem_timedwait, __sanitizer_sem_t *s, void *abstime) {
6310 void *ctx;
6311 COMMON_INTERCEPTOR_ENTER(ctx, sem_timedwait, s, abstime);
6312 COMMON_INTERCEPTOR_READ_RANGE(ctx, abstime, struct_timespec_sz);
6313 int res = COMMON_INTERCEPTOR_BLOCK_REAL(sem_timedwait)(s, abstime);
6314 if (res == 0) {
6315 COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s);
6316 }
6317 return res;
6318}
6319
6320INTERCEPTOR(int, sem_post, __sanitizer_sem_t *s) {
6321 void *ctx;
6322 COMMON_INTERCEPTOR_ENTER(ctx, sem_post, s);
6323 COMMON_INTERCEPTOR_RELEASE(ctx, (uptr)s);
6324 int res = REAL(sem_post)(s);
6325 return res;
6326}
6327
6328INTERCEPTOR(int, sem_getvalue, __sanitizer_sem_t *s, int *sval) {
6329 void *ctx;
6330 COMMON_INTERCEPTOR_ENTER(ctx, sem_getvalue, s, sval);
6331 int res = REAL(sem_getvalue)(s, sval);
6332 if (res == 0) {
6333 COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s);
6334 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sval, sizeof(*sval));
6335 }
6336 return res;
6337}
6338#define INIT_SEM \
6339 COMMON_INTERCEPT_FUNCTION(sem_init); \
6340 COMMON_INTERCEPT_FUNCTION(sem_destroy); \
6341 COMMON_INTERCEPT_FUNCTION(sem_wait); \
6342 COMMON_INTERCEPT_FUNCTION(sem_trywait); \
6343 COMMON_INTERCEPT_FUNCTION(sem_timedwait); \
6344 COMMON_INTERCEPT_FUNCTION(sem_post); \
6345 COMMON_INTERCEPT_FUNCTION(sem_getvalue);
6346#else
6347#define INIT_SEM
6348#endif // SANITIZER_INTERCEPT_SEM
6349
6350#if SANITIZER_INTERCEPT_PTHREAD_SETCANCEL
6351INTERCEPTOR(int, pthread_setcancelstate, int state, int *oldstate) {
6352 void *ctx;
6353 COMMON_INTERCEPTOR_ENTER(ctx, pthread_setcancelstate, state, oldstate);
6354 int res = REAL(pthread_setcancelstate)(state, oldstate);
6355 if (res == 0 && oldstate != nullptr)
6356 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldstate, sizeof(*oldstate));
6357 return res;
6358}
6359
6360INTERCEPTOR(int, pthread_setcanceltype, int type, int *oldtype) {
6361 void *ctx;
6362 COMMON_INTERCEPTOR_ENTER(ctx, pthread_setcanceltype, type, oldtype);
6363 int res = REAL(pthread_setcanceltype)(type, oldtype);
6364 if (res == 0 && oldtype != nullptr)
6365 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldtype, sizeof(*oldtype));
6366 return res;
6367}
6368#define INIT_PTHREAD_SETCANCEL \
6369 COMMON_INTERCEPT_FUNCTION(pthread_setcancelstate); \
6370 COMMON_INTERCEPT_FUNCTION(pthread_setcanceltype);
6371#else
6372#define INIT_PTHREAD_SETCANCEL
6373#endif
6374
6375#if SANITIZER_INTERCEPT_MINCORE
6376INTERCEPTOR(int, mincore, void *addr, uptr length, unsigned char *vec) {
6377 void *ctx;
6378 COMMON_INTERCEPTOR_ENTER(ctx, mincore, addr, length, vec);
6379 int res = REAL(mincore)(addr, length, vec);
6380 if (res == 0) {
6381 uptr page_size = GetPageSizeCached();
6382 uptr vec_size = ((length + page_size - 1) & (~(page_size - 1))) / page_size;
6383 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, vec, vec_size);
6384 }
6385 return res;
6386}
6387#define INIT_MINCORE COMMON_INTERCEPT_FUNCTION(mincore);
6388#else
6389#define INIT_MINCORE
6390#endif
6391
6392#if SANITIZER_INTERCEPT_PROCESS_VM_READV
6393INTERCEPTOR(SSIZE_T, process_vm_readv, int pid, __sanitizer_iovec *local_iov,
6394 uptr liovcnt, __sanitizer_iovec *remote_iov, uptr riovcnt,
6395 uptr flags) {
6396 void *ctx;
6397 COMMON_INTERCEPTOR_ENTER(ctx, process_vm_readv, pid, local_iov, liovcnt,
6398 remote_iov, riovcnt, flags);
6399 SSIZE_T res = REAL(process_vm_readv)(pid, local_iov, liovcnt, remote_iov,
6400 riovcnt, flags);
6401 if (res > 0)
6402 write_iovec(ctx, local_iov, liovcnt, res);
6403 return res;
6404}
6405
6406INTERCEPTOR(SSIZE_T, process_vm_writev, int pid, __sanitizer_iovec *local_iov,
6407 uptr liovcnt, __sanitizer_iovec *remote_iov, uptr riovcnt,
6408 uptr flags) {
6409 void *ctx;
6410 COMMON_INTERCEPTOR_ENTER(ctx, process_vm_writev, pid, local_iov, liovcnt,
6411 remote_iov, riovcnt, flags);
6412 SSIZE_T res = REAL(process_vm_writev)(pid, local_iov, liovcnt, remote_iov,
6413 riovcnt, flags);
6414 if (res > 0)
6415 read_iovec(ctx, local_iov, liovcnt, res);
6416 return res;
6417}
6418#define INIT_PROCESS_VM_READV \
6419 COMMON_INTERCEPT_FUNCTION(process_vm_readv); \
6420 COMMON_INTERCEPT_FUNCTION(process_vm_writev);
6421#else
6422#define INIT_PROCESS_VM_READV
6423#endif
6424
6425#if SANITIZER_INTERCEPT_CTERMID
6426INTERCEPTOR(char *, ctermid, char *s) {
6427 void *ctx;
6428 COMMON_INTERCEPTOR_ENTER(ctx, ctermid, s);
6429 char *res = REAL(ctermid)(s);
6430 if (res) {
6431 COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
6432 }
6433 return res;
6434}
6435#define INIT_CTERMID COMMON_INTERCEPT_FUNCTION(ctermid);
6436#else
6437#define INIT_CTERMID
6438#endif
6439
6440#if SANITIZER_INTERCEPT_CTERMID_R
6441INTERCEPTOR(char *, ctermid_r, char *s) {
6442 void *ctx;
6443 COMMON_INTERCEPTOR_ENTER(ctx, ctermid_r, s);
6444 char *res = REAL(ctermid_r)(s);
6445 if (res) {
6446 COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
6447 }
6448 return res;
6449}
6450#define INIT_CTERMID_R COMMON_INTERCEPT_FUNCTION(ctermid_r);
6451#else
6452#define INIT_CTERMID_R
6453#endif
6454
6455#if SANITIZER_INTERCEPT_RECV_RECVFROM
6456INTERCEPTOR(SSIZE_T, recv, int fd, void *buf, SIZE_T len, int flags) {
6457 void *ctx;
6458 COMMON_INTERCEPTOR_ENTER(ctx, recv, fd, buf, len, flags);
6459 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
6460 SSIZE_T res = REAL(recv)(fd, buf, len, flags);
6461 if (res > 0) {
6462 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, Min((SIZE_T)res, len));
6463 }
6464 if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
6465 return res;
6466}
6467
6468INTERCEPTOR(SSIZE_T, recvfrom, int fd, void *buf, SIZE_T len, int flags,
6469 void *srcaddr, int *addrlen) {
6470 void *ctx;
6471 COMMON_INTERCEPTOR_ENTER(ctx, recvfrom, fd, buf, len, flags, srcaddr,
6472 addrlen);
6473 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
6474 SIZE_T srcaddr_sz;
6475 if (srcaddr) srcaddr_sz = *addrlen;
6476 (void)srcaddr_sz; // prevent "set but not used" warning
6477 SSIZE_T res = REAL(recvfrom)(fd, buf, len, flags, srcaddr, addrlen);
6478 if (res > 0)
6479 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, Min((SIZE_T)res, len));
6480 if (res >= 0 && srcaddr)
6481 COMMON_INTERCEPTOR_INITIALIZE_RANGE(srcaddr,
6482 Min((SIZE_T)*addrlen, srcaddr_sz));
6483 return res;
6484}
6485#define INIT_RECV_RECVFROM \
6486 COMMON_INTERCEPT_FUNCTION(recv); \
6487 COMMON_INTERCEPT_FUNCTION(recvfrom);
6488#else
6489#define INIT_RECV_RECVFROM
6490#endif
6491
6492#if SANITIZER_INTERCEPT_SEND_SENDTO
6493INTERCEPTOR(SSIZE_T, send, int fd, void *buf, SIZE_T len, int flags) {
6494 void *ctx;
6495 COMMON_INTERCEPTOR_ENTER(ctx, send, fd, buf, len, flags);
6496 if (fd >= 0) {
6497 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
6498 COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
6499 }
6500 SSIZE_T res = REAL(send)(fd, buf, len, flags);
6501 if (common_flags()->intercept_send && res > 0)
6502 COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, Min((SIZE_T)res, len));
6503 return res;
6504}
6505
6506INTERCEPTOR(SSIZE_T, sendto, int fd, void *buf, SIZE_T len, int flags,
6507 void *dstaddr, int addrlen) {
6508 void *ctx;
6509 COMMON_INTERCEPTOR_ENTER(ctx, sendto, fd, buf, len, flags, dstaddr, addrlen);
6510 if (fd >= 0) {
6511 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
6512 COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
6513 }
6514 // Can't check dstaddr as it may have uninitialized padding at the end.
6515 SSIZE_T res = REAL(sendto)(fd, buf, len, flags, dstaddr, addrlen);
6516 if (common_flags()->intercept_send && res > 0)
6517 COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, Min((SIZE_T)res, len));
6518 return res;
6519}
6520#define INIT_SEND_SENDTO \
6521 COMMON_INTERCEPT_FUNCTION(send); \
6522 COMMON_INTERCEPT_FUNCTION(sendto);
6523#else
6524#define INIT_SEND_SENDTO
6525#endif
6526
6527#if SANITIZER_INTERCEPT_EVENTFD_READ_WRITE
6528INTERCEPTOR(int, eventfd_read, int fd, u64 *value) {
6529 void *ctx;
6530 COMMON_INTERCEPTOR_ENTER(ctx, eventfd_read, fd, value);
6531 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
6532 int res = REAL(eventfd_read)(fd, value);
6533 if (res == 0) {
6534 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, sizeof(*value));
6535 if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
6536 }
6537 return res;
6538}
6539INTERCEPTOR(int, eventfd_write, int fd, u64 value) {
6540 void *ctx;
6541 COMMON_INTERCEPTOR_ENTER(ctx, eventfd_write, fd, value);
6542 if (fd >= 0) {
6543 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
6544 COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
6545 }
6546 int res = REAL(eventfd_write)(fd, value);
6547 return res;
6548}
6549#define INIT_EVENTFD_READ_WRITE \
6550 COMMON_INTERCEPT_FUNCTION(eventfd_read); \
6551 COMMON_INTERCEPT_FUNCTION(eventfd_write)
6552#else
6553#define INIT_EVENTFD_READ_WRITE
6554#endif
6555
6556#if SANITIZER_INTERCEPT_STAT
6557INTERCEPTOR(int, stat, const char *path, void *buf) {
6558 void *ctx;
6559 COMMON_INTERCEPTOR_ENTER(ctx, stat, path, buf);
6560 if (common_flags()->intercept_stat)
6561 COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
6562 int res = REAL(stat)(path, buf);
6563 if (!res)
6564 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat_sz);
6565 return res;
6566}
6567#define INIT_STAT COMMON_INTERCEPT_FUNCTION(stat)
6568#else
6569#define INIT_STAT
6570#endif
6571
6572#if SANITIZER_INTERCEPT_LSTAT
6573INTERCEPTOR(int, lstat, const char *path, void *buf) {
6574 void *ctx;
6575 COMMON_INTERCEPTOR_ENTER(ctx, lstat, path, buf);
6576 if (common_flags()->intercept_stat)
6577 COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
6578 int res = REAL(lstat)(path, buf);
6579 if (!res)
6580 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat_sz);
6581 return res;
6582}
6583#define INIT_LSTAT COMMON_INTERCEPT_FUNCTION(lstat)
6584#else
6585#define INIT_LSTAT
6586#endif
6587
6588#if SANITIZER_INTERCEPT___XSTAT
6589INTERCEPTOR(int, __xstat, int version, const char *path, void *buf) {
6590 void *ctx;
6591 COMMON_INTERCEPTOR_ENTER(ctx, __xstat, version, path, buf);
6592 if (common_flags()->intercept_stat)
6593 COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
6594 int res = REAL(__xstat)(version, path, buf);
6595 if (!res)
6596 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat_sz);
6597 return res;
6598}
6599#define INIT___XSTAT COMMON_INTERCEPT_FUNCTION(__xstat)
6600#else
6601#define INIT___XSTAT
6602#endif
6603
6604#if SANITIZER_INTERCEPT___XSTAT64
6605INTERCEPTOR(int, __xstat64, int version, const char *path, void *buf) {
6606 void *ctx;
6607 COMMON_INTERCEPTOR_ENTER(ctx, __xstat64, version, path, buf);
6608 if (common_flags()->intercept_stat)
6609 COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
6610 int res = REAL(__xstat64)(version, path, buf);
6611 if (!res)
6612 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat64_sz);
6613 return res;
6614}
6615#define INIT___XSTAT64 COMMON_INTERCEPT_FUNCTION(__xstat64)
6616#else
6617#define INIT___XSTAT64
6618#endif
6619
6620#if SANITIZER_INTERCEPT___LXSTAT
6621INTERCEPTOR(int, __lxstat, int version, const char *path, void *buf) {
6622 void *ctx;
6623 COMMON_INTERCEPTOR_ENTER(ctx, __lxstat, version, path, buf);
6624 if (common_flags()->intercept_stat)
6625 COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
6626 int res = REAL(__lxstat)(version, path, buf);
6627 if (!res)
6628 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat_sz);
6629 return res;
6630}
6631#define INIT___LXSTAT COMMON_INTERCEPT_FUNCTION(__lxstat)
6632#else
6633#define INIT___LXSTAT
6634#endif
6635
6636#if SANITIZER_INTERCEPT___LXSTAT64
6637INTERCEPTOR(int, __lxstat64, int version, const char *path, void *buf) {
6638 void *ctx;
6639 COMMON_INTERCEPTOR_ENTER(ctx, __lxstat64, version, path, buf);
6640 if (common_flags()->intercept_stat)
6641 COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
6642 int res = REAL(__lxstat64)(version, path, buf);
6643 if (!res)
6644 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat64_sz);
6645 return res;
6646}
6647#define INIT___LXSTAT64 COMMON_INTERCEPT_FUNCTION(__lxstat64)
6648#else
6649#define INIT___LXSTAT64
6650#endif
6651
6652// FIXME: add other *stat interceptor
6653
6654#if SANITIZER_INTERCEPT_UTMP
6655INTERCEPTOR(void *, getutent, int dummy) {
6656 void *ctx;
6657 COMMON_INTERCEPTOR_ENTER(ctx, getutent, dummy);
6658 void *res = REAL(getutent)(dummy);
6659 if (res)
6660 COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmp_sz);
6661 return res;
6662}
6663INTERCEPTOR(void *, getutid, void *ut) {
6664 void *ctx;
6665 COMMON_INTERCEPTOR_ENTER(ctx, getutid, ut);
6666 void *res = REAL(getutid)(ut);
6667 if (res)
6668 COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmp_sz);
6669 return res;
6670}
6671INTERCEPTOR(void *, getutline, void *ut) {
6672 void *ctx;
6673 COMMON_INTERCEPTOR_ENTER(ctx, getutline, ut);
6674 void *res = REAL(getutline)(ut);
6675 if (res)
6676 COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmp_sz);
6677 return res;
6678}
6679#define INIT_UTMP \
6680 COMMON_INTERCEPT_FUNCTION(getutent); \
6681 COMMON_INTERCEPT_FUNCTION(getutid); \
6682 COMMON_INTERCEPT_FUNCTION(getutline);
6683#else
6684#define INIT_UTMP
6685#endif
6686
6687#if SANITIZER_INTERCEPT_UTMPX
6688INTERCEPTOR(void *, getutxent, int dummy) {
6689 void *ctx;
6690 COMMON_INTERCEPTOR_ENTER(ctx, getutxent, dummy);
6691 void *res = REAL(getutxent)(dummy);
6692 if (res)
6693 COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmpx_sz);
6694 return res;
6695}
6696INTERCEPTOR(void *, getutxid, void *ut) {
6697 void *ctx;
6698 COMMON_INTERCEPTOR_ENTER(ctx, getutxid, ut);
6699 void *res = REAL(getutxid)(ut);
6700 if (res)
6701 COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmpx_sz);
6702 return res;
6703}
6704INTERCEPTOR(void *, getutxline, void *ut) {
6705 void *ctx;
6706 COMMON_INTERCEPTOR_ENTER(ctx, getutxline, ut);
6707 void *res = REAL(getutxline)(ut);
6708 if (res)
6709 COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmpx_sz);
6710 return res;
6711}
6712INTERCEPTOR(void *, pututxline, const void *ut) {
6713 void *ctx;
6714 COMMON_INTERCEPTOR_ENTER(ctx, pututxline, ut);
6715 if (ut)
6716 COMMON_INTERCEPTOR_READ_RANGE(ctx, ut, __sanitizer::struct_utmpx_sz);
6717 void *res = REAL(pututxline)(ut);
6718 if (res)
6719 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, __sanitizer::struct_utmpx_sz);
6720 return res;
6721}
6722#define INIT_UTMPX \
6723 COMMON_INTERCEPT_FUNCTION(getutxent); \
6724 COMMON_INTERCEPT_FUNCTION(getutxid); \
6725 COMMON_INTERCEPT_FUNCTION(getutxline); \
6726 COMMON_INTERCEPT_FUNCTION(pututxline);
6727#else
6728#define INIT_UTMPX
6729#endif
6730
6731#if SANITIZER_INTERCEPT_GETLOADAVG
6732INTERCEPTOR(int, getloadavg, double *loadavg, int nelem) {
6733 void *ctx;
6734 COMMON_INTERCEPTOR_ENTER(ctx, getloadavg, loadavg, nelem);
6735 int res = REAL(getloadavg)(loadavg, nelem);
6736 if (res > 0)
6737 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, loadavg, res * sizeof(*loadavg));
6738 return res;
6739}
6740#define INIT_GETLOADAVG \
6741 COMMON_INTERCEPT_FUNCTION(getloadavg);
6742#else
6743#define INIT_GETLOADAVG
6744#endif
6745
6746#if SANITIZER_INTERCEPT_MCHECK_MPROBE
6747INTERCEPTOR(int, mcheck, void (*abortfunc)(int mstatus)) {
6748 return 0;
6749}
6750
6751INTERCEPTOR(int, mcheck_pedantic, void (*abortfunc)(int mstatus)) {
6752 return 0;
6753}
6754
6755INTERCEPTOR(int, mprobe, void *ptr) {
6756 return 0;
6757}
6758#endif
6759
6760INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) {
6761 void *ctx;
6762 COMMON_INTERCEPTOR_ENTER(ctx, wcslen, s);
6763 SIZE_T res = REAL(wcslen)(s);
6764 COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(wchar_t) * (res + 1));
6765 return res;
6766}
6767
6768INTERCEPTOR(SIZE_T, wcsnlen, const wchar_t *s, SIZE_T n) {
6769 void *ctx;
6770 COMMON_INTERCEPTOR_ENTER(ctx, wcsnlen, s, n);
6771 SIZE_T res = REAL(wcsnlen)(s, n);
6772 COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(wchar_t) * Min(res + 1, n));
6773 return res;
6774}
6775#define INIT_WCSLEN \
6776 COMMON_INTERCEPT_FUNCTION(wcslen); \
6777 COMMON_INTERCEPT_FUNCTION(wcsnlen);
6778
6779#if SANITIZER_INTERCEPT_WCSCAT
6780INTERCEPTOR(wchar_t *, wcscat, wchar_t *dst, const wchar_t *src) {
6781 void *ctx;
6782 COMMON_INTERCEPTOR_ENTER(ctx, wcscat, dst, src);
6783 SIZE_T src_size = REAL(wcslen)(src);
6784 SIZE_T dst_size = REAL(wcslen)(dst);
6785 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, (src_size + 1) * sizeof(wchar_t));
6786 COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t));
6787 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst + dst_size,
6788 (src_size + 1) * sizeof(wchar_t));
6789 return REAL(wcscat)(dst, src);
6790}
6791
6792INTERCEPTOR(wchar_t *, wcsncat, wchar_t *dst, const wchar_t *src, SIZE_T n) {
6793 void *ctx;
6794 COMMON_INTERCEPTOR_ENTER(ctx, wcsncat, dst, src, n);
6795 SIZE_T src_size = REAL(wcsnlen)(src, n);
6796 SIZE_T dst_size = REAL(wcslen)(dst);
6797 COMMON_INTERCEPTOR_READ_RANGE(ctx, src,
6798 Min(src_size + 1, n) * sizeof(wchar_t));
6799 COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t));
6800 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst + dst_size,
6801 (src_size + 1) * sizeof(wchar_t));
6802 return REAL(wcsncat)(dst, src, n);
6803}
6804#define INIT_WCSCAT \
6805 COMMON_INTERCEPT_FUNCTION(wcscat); \
6806 COMMON_INTERCEPT_FUNCTION(wcsncat);
6807#else
6808#define INIT_WCSCAT
6809#endif
6810
6811#if SANITIZER_INTERCEPT_WCSDUP
6812INTERCEPTOR(wchar_t *, wcsdup, wchar_t *s) {
6813 void *ctx;
6814 COMMON_INTERCEPTOR_ENTER(ctx, wcsdup, s);
6815 SIZE_T len = REAL(wcslen)(s);
6816 COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(wchar_t) * (len + 1));
6817 wchar_t *result = REAL(wcsdup)(s);
6818 if (result)
6819 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(wchar_t) * (len + 1));
6820 return result;
6821}
6822
6823#define INIT_WCSDUP COMMON_INTERCEPT_FUNCTION(wcsdup);
6824#else
6825#define INIT_WCSDUP
6826#endif
6827
6828#if SANITIZER_INTERCEPT_STRXFRM
6829static SIZE_T RealStrLen(const char *str) { return REAL(strlen)(str); }
6830
6831static SIZE_T RealStrLen(const wchar_t *str) { return REAL(wcslen)(str); }
6832
6833#define STRXFRM_INTERCEPTOR_IMPL(strxfrm, dest, src, len, ...) \
6834 { \
6835 void *ctx; \
6836 COMMON_INTERCEPTOR_ENTER(ctx, strxfrm, dest, src, len, ##__VA_ARGS__); \
6837 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, \
6838 sizeof(*src) * (RealStrLen(src) + 1)); \
6839 SIZE_T res = REAL(strxfrm)(dest, src, len, ##__VA_ARGS__); \
6840 if (res < len) \
6841 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, sizeof(*src) * (res + 1)); \
6842 return res; \
6843 }
6844
6845INTERCEPTOR(SIZE_T, strxfrm, char *dest, const char *src, SIZE_T len) {
6846 STRXFRM_INTERCEPTOR_IMPL(strxfrm, dest, src, len);
6847}
6848
6849INTERCEPTOR(SIZE_T, strxfrm_l, char *dest, const char *src, SIZE_T len,
6850 void *locale) {
6851 STRXFRM_INTERCEPTOR_IMPL(strxfrm_l, dest, src, len, locale);
6852}
6853
6854#define INIT_STRXFRM \
6855 COMMON_INTERCEPT_FUNCTION(strxfrm); \
6856 COMMON_INTERCEPT_FUNCTION(strxfrm_l);
6857#else
6858#define INIT_STRXFRM
6859#endif
6860
6861#if SANITIZER_INTERCEPT___STRXFRM_L
6862INTERCEPTOR(SIZE_T, __strxfrm_l, char *dest, const char *src, SIZE_T len,
6863 void *locale) {
6864 STRXFRM_INTERCEPTOR_IMPL(__strxfrm_l, dest, src, len, locale);
6865}
6866
6867#define INIT___STRXFRM_L COMMON_INTERCEPT_FUNCTION(__strxfrm_l);
6868#else
6869#define INIT___STRXFRM_L
6870#endif
6871
6872#if SANITIZER_INTERCEPT_WCSXFRM
6873INTERCEPTOR(SIZE_T, wcsxfrm, wchar_t *dest, const wchar_t *src, SIZE_T len) {
6874 STRXFRM_INTERCEPTOR_IMPL(wcsxfrm, dest, src, len);
6875}
6876
6877INTERCEPTOR(SIZE_T, wcsxfrm_l, wchar_t *dest, const wchar_t *src, SIZE_T len,
6878 void *locale) {
6879 STRXFRM_INTERCEPTOR_IMPL(wcsxfrm_l, dest, src, len, locale);
6880}
6881
6882#define INIT_WCSXFRM \
6883 COMMON_INTERCEPT_FUNCTION(wcsxfrm); \
6884 COMMON_INTERCEPT_FUNCTION(wcsxfrm_l);
6885#else
6886#define INIT_WCSXFRM
6887#endif
6888
6889#if SANITIZER_INTERCEPT___WCSXFRM_L
6890INTERCEPTOR(SIZE_T, __wcsxfrm_l, wchar_t *dest, const wchar_t *src, SIZE_T len,
6891 void *locale) {
6892 STRXFRM_INTERCEPTOR_IMPL(__wcsxfrm_l, dest, src, len, locale);
6893}
6894
6895#define INIT___WCSXFRM_L COMMON_INTERCEPT_FUNCTION(__wcsxfrm_l);
6896#else
6897#define INIT___WCSXFRM_L
6898#endif
6899
6900#if SANITIZER_INTERCEPT_ACCT
6901INTERCEPTOR(int, acct, const char *file) {
6902 void *ctx;
6903 COMMON_INTERCEPTOR_ENTER(ctx, acct, file);
6904 if (file)
6905 COMMON_INTERCEPTOR_READ_RANGE(ctx, file, REAL(strlen)(file) + 1);
6906 return REAL(acct)(file);
6907}
6908#define INIT_ACCT COMMON_INTERCEPT_FUNCTION(acct)
6909#else
6910#define INIT_ACCT
6911#endif
6912
6913#if SANITIZER_INTERCEPT_USER_FROM_UID
6914INTERCEPTOR(const char *, user_from_uid, u32 uid, int nouser) {
6915 void *ctx;
6916 const char *user;
6917 COMMON_INTERCEPTOR_ENTER(ctx, user_from_uid, uid, nouser);
6918 user = REAL(user_from_uid)(uid, nouser);
6919 if (user)
6920 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, user, REAL(strlen)(user) + 1);
6921 return user;
6922}
6923#define INIT_USER_FROM_UID COMMON_INTERCEPT_FUNCTION(user_from_uid)
6924#else
6925#define INIT_USER_FROM_UID
6926#endif
6927
6928#if SANITIZER_INTERCEPT_UID_FROM_USER
6929INTERCEPTOR(int, uid_from_user, const char *name, u32 *uid) {
6930 void *ctx;
6931 int res;
6932 COMMON_INTERCEPTOR_ENTER(ctx, uid_from_user, name, uid);
6933 if (name)
6934 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
6935 res = REAL(uid_from_user)(name, uid);
6936 if (uid)
6937 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, uid, sizeof(*uid));
6938 return res;
6939}
6940#define INIT_UID_FROM_USER COMMON_INTERCEPT_FUNCTION(uid_from_user)
6941#else
6942#define INIT_UID_FROM_USER
6943#endif
6944
6945#if SANITIZER_INTERCEPT_GROUP_FROM_GID
6946INTERCEPTOR(const char *, group_from_gid, u32 gid, int nogroup) {
6947 void *ctx;
6948 const char *group;
6949 COMMON_INTERCEPTOR_ENTER(ctx, group_from_gid, gid, nogroup);
6950 group = REAL(group_from_gid)(gid, nogroup);
6951 if (group)
6952 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, group, REAL(strlen)(group) + 1);
6953 return group;
6954}
6955#define INIT_GROUP_FROM_GID COMMON_INTERCEPT_FUNCTION(group_from_gid)
6956#else
6957#define INIT_GROUP_FROM_GID
6958#endif
6959
6960#if SANITIZER_INTERCEPT_GID_FROM_GROUP
6961INTERCEPTOR(int, gid_from_group, const char *group, u32 *gid) {
6962 void *ctx;
6963 int res;
6964 COMMON_INTERCEPTOR_ENTER(ctx, gid_from_group, group, gid);
6965 if (group)
6966 COMMON_INTERCEPTOR_READ_RANGE(ctx, group, REAL(strlen)(group) + 1);
6967 res = REAL(gid_from_group)(group, gid);
6968 if (gid)
6969 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, gid, sizeof(*gid));
6970 return res;
6971}
6972#define INIT_GID_FROM_GROUP COMMON_INTERCEPT_FUNCTION(gid_from_group)
6973#else
6974#define INIT_GID_FROM_GROUP
6975#endif
6976
6977#if SANITIZER_INTERCEPT_ACCESS
6978INTERCEPTOR(int, access, const char *path, int mode) {
6979 void *ctx;
6980 COMMON_INTERCEPTOR_ENTER(ctx, access, path, mode);
6981 if (path)
6982 COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
6983 return REAL(access)(path, mode);
6984}
6985#define INIT_ACCESS COMMON_INTERCEPT_FUNCTION(access)
6986#else
6987#define INIT_ACCESS
6988#endif
6989
6990#if SANITIZER_INTERCEPT_FACCESSAT
6991INTERCEPTOR(int, faccessat, int fd, const char *path, int mode, int flags) {
6992 void *ctx;
6993 COMMON_INTERCEPTOR_ENTER(ctx, faccessat, fd, path, mode, flags);
6994 if (path)
6995 COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
6996 return REAL(faccessat)(fd, path, mode, flags);
6997}
6998#define INIT_FACCESSAT COMMON_INTERCEPT_FUNCTION(faccessat)
6999#else
7000#define INIT_FACCESSAT
7001#endif
7002
7003#if SANITIZER_INTERCEPT_GETGROUPLIST
7004INTERCEPTOR(int, getgrouplist, const char *name, u32 basegid, u32 *groups,
7005 int *ngroups) {
7006 void *ctx;
7007 int res;
7008 COMMON_INTERCEPTOR_ENTER(ctx, getgrouplist, name, basegid, groups, ngroups);
7009 if (name)
7010 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
7011 if (ngroups)
7012 COMMON_INTERCEPTOR_READ_RANGE(ctx, ngroups, sizeof(*ngroups));
7013 res = REAL(getgrouplist)(name, basegid, groups, ngroups);
7014 if (!res && groups && ngroups) {
7015 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, groups, sizeof(*groups) * (*ngroups));
7016 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ngroups, sizeof(*ngroups));
7017 }
7018 return res;
7019}
7020
7021#define INIT_GETGROUPLIST COMMON_INTERCEPT_FUNCTION(getgrouplist);
7022#else
7023#define INIT_GETGROUPLIST
7024#endif
7025
7026#if SANITIZER_INTERCEPT_GETGROUPMEMBERSHIP
7027INTERCEPTOR(int, getgroupmembership, const char *name, u32 basegid, u32 *groups,
7028 int maxgrp, int *ngroups) {
7029 void *ctx;
7030 int res;
7031 COMMON_INTERCEPTOR_ENTER(ctx, getgroupmembership, name, basegid, groups,
7032 maxgrp, ngroups);
7033 if (name)
7034 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
7035 res = REAL(getgroupmembership)(name, basegid, groups, maxgrp, ngroups);
7036 if (!res && groups && ngroups) {
7037 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, groups, sizeof(*groups) * (*ngroups));
7038 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ngroups, sizeof(*ngroups));
7039 }
7040 return res;
7041}
7042
7043#define INIT_GETGROUPMEMBERSHIP COMMON_INTERCEPT_FUNCTION(getgroupmembership);
7044#else
7045#define INIT_GETGROUPMEMBERSHIP
7046#endif
7047
7048#if SANITIZER_INTERCEPT_READLINK
7049INTERCEPTOR(SSIZE_T, readlink, const char *path, char *buf, SIZE_T bufsiz) {
7050 void* ctx;
7051 COMMON_INTERCEPTOR_ENTER(ctx, readlink, path, buf, bufsiz);
7052 COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
7053 SSIZE_T res = REAL(readlink)(path, buf, bufsiz);
7054 if (res > 0)
7055 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, res);
7056 return res;
7057}
7058
7059#define INIT_READLINK COMMON_INTERCEPT_FUNCTION(readlink)
7060#else
7061#define INIT_READLINK
7062#endif
7063
7064#if SANITIZER_INTERCEPT_READLINKAT
7065INTERCEPTOR(SSIZE_T, readlinkat, int dirfd, const char *path, char *buf,
7066 SIZE_T bufsiz) {
7067 void* ctx;
7068 COMMON_INTERCEPTOR_ENTER(ctx, readlinkat, dirfd, path, buf, bufsiz);
7069 COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
7070 SSIZE_T res = REAL(readlinkat)(dirfd, path, buf, bufsiz);
7071 if (res > 0)
7072 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, res);
7073 return res;
7074}
7075
7076#define INIT_READLINKAT COMMON_INTERCEPT_FUNCTION(readlinkat)
7077#else
7078#define INIT_READLINKAT
7079#endif
7080
7081#if SANITIZER_INTERCEPT_NAME_TO_HANDLE_AT
7082INTERCEPTOR(int, name_to_handle_at, int dirfd, const char *pathname,
7083 struct file_handle *handle, int *mount_id, int flags) {
7084 void* ctx;
7085 COMMON_INTERCEPTOR_ENTER(ctx, name_to_handle_at, dirfd, pathname, handle,
7086 mount_id, flags);
7087 COMMON_INTERCEPTOR_READ_RANGE(ctx, pathname, REAL(strlen)(pathname) + 1);
7088
7089 __sanitizer_file_handle *sanitizer_handle =
7090 reinterpret_cast<__sanitizer_file_handle*>(handle);
7091 COMMON_INTERCEPTOR_READ_RANGE(
7092 ctx, &sanitizer_handle->handle_bytes,
7093 sizeof(sanitizer_handle->handle_bytes));
7094
7095 int res = REAL(name_to_handle_at)(dirfd, pathname, handle, mount_id, flags);
7096 if (!res) {
7097 COMMON_INTERCEPTOR_WRITE_RANGE(
7098 ctx, &sanitizer_handle->handle_bytes,
7099 sizeof(sanitizer_handle->handle_bytes));
7100 COMMON_INTERCEPTOR_WRITE_RANGE(
7101 ctx, &sanitizer_handle->handle_type,
7102 sizeof(sanitizer_handle->handle_type));
7103 COMMON_INTERCEPTOR_WRITE_RANGE(
7104 ctx, &sanitizer_handle->f_handle, sanitizer_handle->handle_bytes);
7105 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mount_id, sizeof(*mount_id));
7106 }
7107 return res;
7108}
7109
7110#define INIT_NAME_TO_HANDLE_AT COMMON_INTERCEPT_FUNCTION(name_to_handle_at)
7111#else
7112#define INIT_NAME_TO_HANDLE_AT
7113#endif
7114
7115#if SANITIZER_INTERCEPT_OPEN_BY_HANDLE_AT
7116INTERCEPTOR(int, open_by_handle_at, int mount_fd, struct file_handle* handle,
7117 int flags) {
7118 void* ctx;
7119 COMMON_INTERCEPTOR_ENTER(ctx, open_by_handle_at, mount_fd, handle, flags);
7120
7121 __sanitizer_file_handle *sanitizer_handle =
7122 reinterpret_cast<__sanitizer_file_handle*>(handle);
7123 COMMON_INTERCEPTOR_READ_RANGE(
7124 ctx, &sanitizer_handle->handle_bytes,
7125 sizeof(sanitizer_handle->handle_bytes));
7126 COMMON_INTERCEPTOR_READ_RANGE(
7127 ctx, &sanitizer_handle->handle_type,
7128 sizeof(sanitizer_handle->handle_type));
7129 COMMON_INTERCEPTOR_READ_RANGE(
7130 ctx, &sanitizer_handle->f_handle, sanitizer_handle->handle_bytes);
7131
7132 return REAL(open_by_handle_at)(mount_fd, handle, flags);
7133}
7134
7135#define INIT_OPEN_BY_HANDLE_AT COMMON_INTERCEPT_FUNCTION(open_by_handle_at)
7136#else
7137#define INIT_OPEN_BY_HANDLE_AT
7138#endif
7139
7140#if SANITIZER_INTERCEPT_STRLCPY
7141INTERCEPTOR(SIZE_T, strlcpy, char *dst, char *src, SIZE_T size) {
7142 void *ctx;
7143 SIZE_T res;
7144 COMMON_INTERCEPTOR_ENTER(ctx, strlcpy, dst, src, size);
7145 if (src) {
7146 // Keep strnlen as macro argument, as macro may ignore it.
7147 COMMON_INTERCEPTOR_READ_STRING(
7148 ctx, src, Min(internal_strnlen(src, size), size - 1) + 1);
7149 }
7150 res = REAL(strlcpy)(dst, src, size);
7151 COMMON_INTERCEPTOR_COPY_STRING(ctx, dst, src, REAL(strlen)(dst) + 1);
7152 return res;
7153}
7154
7155INTERCEPTOR(SIZE_T, strlcat, char *dst, char *src, SIZE_T size) {
7156 void *ctx;
7157 SIZE_T len = 0;
7158 COMMON_INTERCEPTOR_ENTER(ctx, strlcat, dst, src, size);
7159 // src is checked in the strlcpy() interceptor
7160 if (dst) {
7161 len = internal_strnlen(dst, size);
7162 COMMON_INTERCEPTOR_READ_STRING(ctx, dst, Min(len, size - 1) + 1);
7163 }
7164 // Reuse the rest of the code in the strlcpy() interceptor
7165 return WRAP(strlcpy)(dst + len, src, size - len) + len;
7166}
7167#define INIT_STRLCPY \
7168 COMMON_INTERCEPT_FUNCTION(strlcpy); \
7169 COMMON_INTERCEPT_FUNCTION(strlcat);
7170#else
7171#define INIT_STRLCPY
7172#endif
7173
7174#if SANITIZER_INTERCEPT_MMAP
7175INTERCEPTOR(void *, mmap, void *addr, SIZE_T sz, int prot, int flags, int fd,
7176 OFF_T off) {
7177 void *ctx;
7178 if (common_flags()->detect_write_exec)
7179 ReportMmapWriteExec(prot);
7180 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
7181 return (void *)internal_mmap(addr, sz, prot, flags, fd, off);
7182 COMMON_INTERCEPTOR_ENTER(ctx, mmap, addr, sz, prot, flags, fd, off);
7183 COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, sz, prot, flags, fd, off);
7184}
7185
7186INTERCEPTOR(int, mprotect, void *addr, SIZE_T sz, int prot) {
7187 void *ctx;
7188 if (common_flags()->detect_write_exec)
7189 ReportMmapWriteExec(prot);
7190 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
7191 return (int)internal_mprotect(addr, sz, prot);
7192 COMMON_INTERCEPTOR_ENTER(ctx, mprotect, addr, sz, prot);
7193 MprotectMallocZones(addr, prot);
7194 return REAL(mprotect)(addr, sz, prot);
7195}
7196#define INIT_MMAP \
7197 COMMON_INTERCEPT_FUNCTION(mmap); \
7198 COMMON_INTERCEPT_FUNCTION(mprotect);
7199#else
7200#define INIT_MMAP
7201#endif
7202
7203#if SANITIZER_INTERCEPT_MMAP64
7204INTERCEPTOR(void *, mmap64, void *addr, SIZE_T sz, int prot, int flags, int fd,
7205 OFF64_T off) {
7206 void *ctx;
7207 if (common_flags()->detect_write_exec)
7208 ReportMmapWriteExec(prot);
7209 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
7210 return (void *)internal_mmap(addr, sz, prot, flags, fd, off);
7211 COMMON_INTERCEPTOR_ENTER(ctx, mmap64, addr, sz, prot, flags, fd, off);
7212 COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap64, addr, sz, prot, flags, fd, off);
7213}
7214#define INIT_MMAP64 COMMON_INTERCEPT_FUNCTION(mmap64);
7215#else
7216#define INIT_MMAP64
7217#endif
7218
7219#if SANITIZER_INTERCEPT_DEVNAME
7220INTERCEPTOR(char *, devname, u64 dev, u32 type) {
7221 void *ctx;
7222 char *name;
7223 COMMON_INTERCEPTOR_ENTER(ctx, devname, dev, type);
7224 name = REAL(devname)(dev, type);
7225 if (name)
7226 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, REAL(strlen)(name) + 1);
7227 return name;
7228}
7229#define INIT_DEVNAME COMMON_INTERCEPT_FUNCTION(devname);
7230#else
7231#define INIT_DEVNAME
7232#endif
7233
7234#if SANITIZER_INTERCEPT_DEVNAME_R
7235#if SANITIZER_NETBSD
7236#define DEVNAME_R_RETTYPE int
7237#define DEVNAME_R_SUCCESS(x) (!(x))
7238#else
7239#define DEVNAME_R_RETTYPE char*
7240#define DEVNAME_R_SUCCESS(x) (x)
7241#endif
7242INTERCEPTOR(DEVNAME_R_RETTYPE, devname_r, u64 dev, u32 type, char *path,
7243 uptr len) {
7244 void *ctx;
7245 COMMON_INTERCEPTOR_ENTER(ctx, devname_r, dev, type, path, len);
7246 DEVNAME_R_RETTYPE res = REAL(devname_r)(dev, type, path, len);
7247 if (DEVNAME_R_SUCCESS(res))
7248 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, path, REAL(strlen)(path) + 1);
7249 return res;
7250}
7251#define INIT_DEVNAME_R COMMON_INTERCEPT_FUNCTION(devname_r);
7252#else
7253#define INIT_DEVNAME_R
7254#endif
7255
7256#if SANITIZER_INTERCEPT_FGETLN
7257INTERCEPTOR(char *, fgetln, __sanitizer_FILE *stream, SIZE_T *len) {
7258 void *ctx;
7259 COMMON_INTERCEPTOR_ENTER(ctx, fgetln, stream, len);
7260 char *str = REAL(fgetln)(stream, len);
7261 if (str && len) {
7262 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, len, sizeof(*len));
7263 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, str, *len);
7264 }
7265 return str;
7266}
7267#define INIT_FGETLN COMMON_INTERCEPT_FUNCTION(fgetln)
7268#else
7269#define INIT_FGETLN
7270#endif
7271
7272#if SANITIZER_INTERCEPT_STRMODE
7273INTERCEPTOR(void, strmode, u32 mode, char *bp) {
7274 void *ctx;
7275 COMMON_INTERCEPTOR_ENTER(ctx, strmode, mode, bp);
7276 REAL(strmode)(mode, bp);
7277 if (bp)
7278 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, bp, REAL(strlen)(bp) + 1);
7279}
7280#define INIT_STRMODE COMMON_INTERCEPT_FUNCTION(strmode)
7281#else
7282#define INIT_STRMODE
7283#endif
7284
7285#if SANITIZER_INTERCEPT_TTYENT
7286INTERCEPTOR(struct __sanitizer_ttyent *, getttyent, void) {
7287 void *ctx;
7288 COMMON_INTERCEPTOR_ENTER(ctx, getttyent);
7289 struct __sanitizer_ttyent *ttyent = REAL(getttyent)();
7290 if (ttyent)
7291 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ttyent, struct_ttyent_sz);
7292 return ttyent;
7293}
7294INTERCEPTOR(struct __sanitizer_ttyent *, getttynam, char *name) {
7295 void *ctx;
7296 COMMON_INTERCEPTOR_ENTER(ctx, getttynam, name);
7297 if (name)
7298 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
7299 struct __sanitizer_ttyent *ttyent = REAL(getttynam)(name);
7300 if (ttyent)
7301 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ttyent, struct_ttyent_sz);
7302 return ttyent;
7303}
7304INTERCEPTOR(int, setttyentpath, char *path) {
7305 void *ctx;
7306 COMMON_INTERCEPTOR_ENTER(ctx, setttyentpath, path);
7307 if (path)
7308 COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
7309 return REAL(setttyentpath)(path);
7310}
7311#define INIT_TTYENT \
7312 COMMON_INTERCEPT_FUNCTION(getttyent); \
7313 COMMON_INTERCEPT_FUNCTION(getttynam); \
7314 COMMON_INTERCEPT_FUNCTION(setttyentpath)
7315#else
7316#define INIT_TTYENT
7317#endif
7318
7319#if SANITIZER_INTERCEPT_PROTOENT
7320static void write_protoent(void *ctx, struct __sanitizer_protoent *p) {
7321 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
7322
7323 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_name, REAL(strlen)(p->p_name) + 1);
7324
7325 SIZE_T pp_size = 1; // One handles the trailing \0
7326
7327 for (char **pp = p->p_aliases; *pp; ++pp, ++pp_size)
7328 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *pp, REAL(strlen)(*pp) + 1);
7329
7330 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_aliases,
7331 pp_size * sizeof(char **));
7332}
7333
7334INTERCEPTOR(struct __sanitizer_protoent *, getprotoent) {
7335 void *ctx;
7336 COMMON_INTERCEPTOR_ENTER(ctx, getprotoent);
7337 struct __sanitizer_protoent *p = REAL(getprotoent)();
7338 if (p)
7339 write_protoent(ctx, p);
7340 return p;
7341}
7342
7343INTERCEPTOR(struct __sanitizer_protoent *, getprotobyname, const char *name) {
7344 void *ctx;
7345 COMMON_INTERCEPTOR_ENTER(ctx, getprotobyname, name);
7346 if (name)
7347 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
7348 struct __sanitizer_protoent *p = REAL(getprotobyname)(name);
7349 if (p)
7350 write_protoent(ctx, p);
7351 return p;
7352}
7353
7354INTERCEPTOR(struct __sanitizer_protoent *, getprotobynumber, int proto) {
7355 void *ctx;
7356 COMMON_INTERCEPTOR_ENTER(ctx, getprotobynumber, proto);
7357 struct __sanitizer_protoent *p = REAL(getprotobynumber)(proto);
7358 if (p)
7359 write_protoent(ctx, p);
7360 return p;
7361}
7362#define INIT_PROTOENT \
7363 COMMON_INTERCEPT_FUNCTION(getprotoent); \
7364 COMMON_INTERCEPT_FUNCTION(getprotobyname); \
7365 COMMON_INTERCEPT_FUNCTION(getprotobynumber)
7366#else
7367#define INIT_PROTOENT
7368#endif
7369
7370#if SANITIZER_INTERCEPT_PROTOENT_R
7371INTERCEPTOR(int, getprotoent_r, struct __sanitizer_protoent *result_buf,
7372 char *buf, SIZE_T buflen, struct __sanitizer_protoent **result) {
7373 void *ctx;
7374 COMMON_INTERCEPTOR_ENTER(ctx, getprotoent_r, result_buf, buf, buflen,
7375 result);
7376 int res = REAL(getprotoent_r)(result_buf, buf, buflen, result);
7377
7378 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof *result);
7379 if (!res && *result)
7380 write_protoent(ctx, *result);
7381 return res;
7382}
7383
7384INTERCEPTOR(int, getprotobyname_r, const char *name,
7385 struct __sanitizer_protoent *result_buf, char *buf, SIZE_T buflen,
7386 struct __sanitizer_protoent **result) {
7387 void *ctx;
7388 COMMON_INTERCEPTOR_ENTER(ctx, getprotobyname_r, name, result_buf, buf,
7389 buflen, result);
7390 if (name)
7391 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
7392 int res = REAL(getprotobyname_r)(name, result_buf, buf, buflen, result);
7393
7394 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof *result);
7395 if (!res && *result)
7396 write_protoent(ctx, *result);
7397 return res;
7398}
7399
7400INTERCEPTOR(int, getprotobynumber_r, int num,
7401 struct __sanitizer_protoent *result_buf, char *buf,
7402 SIZE_T buflen, struct __sanitizer_protoent **result) {
7403 void *ctx;
7404 COMMON_INTERCEPTOR_ENTER(ctx, getprotobynumber_r, num, result_buf, buf,
7405 buflen, result);
7406 int res = REAL(getprotobynumber_r)(num, result_buf, buf, buflen, result);
7407
7408 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof *result);
7409 if (!res && *result)
7410 write_protoent(ctx, *result);
7411 return res;
7412}
7413
7414#define INIT_PROTOENT_R \
7415 COMMON_INTERCEPT_FUNCTION(getprotoent_r); \
7416 COMMON_INTERCEPT_FUNCTION(getprotobyname_r); \
7417 COMMON_INTERCEPT_FUNCTION(getprotobynumber_r);
7418#else
7419#define INIT_PROTOENT_R
7420#endif
7421
7422#if SANITIZER_INTERCEPT_NETENT
7423INTERCEPTOR(struct __sanitizer_netent *, getnetent) {
7424 void *ctx;
7425 COMMON_INTERCEPTOR_ENTER(ctx, getnetent);
7426 struct __sanitizer_netent *n = REAL(getnetent)();
7427 if (n) {
7428 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));
7429
7430 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, REAL(strlen)(n->n_name) + 1);
7431
7432 SIZE_T nn_size = 1; // One handles the trailing \0
7433
7434 for (char **nn = n->n_aliases; *nn; ++nn, ++nn_size)
7435 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, REAL(strlen)(*nn) + 1);
7436
7437 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases,
7438 nn_size * sizeof(char **));
7439 }
7440 return n;
7441}
7442
7443INTERCEPTOR(struct __sanitizer_netent *, getnetbyname, const char *name) {
7444 void *ctx;
7445 COMMON_INTERCEPTOR_ENTER(ctx, getnetbyname, name);
7446 if (name)
7447 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
7448 struct __sanitizer_netent *n = REAL(getnetbyname)(name);
7449 if (n) {
7450 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));
7451
7452 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, REAL(strlen)(n->n_name) + 1);
7453
7454 SIZE_T nn_size = 1; // One handles the trailing \0
7455
7456 for (char **nn = n->n_aliases; *nn; ++nn, ++nn_size)
7457 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, REAL(strlen)(*nn) + 1);
7458
7459 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases,
7460 nn_size * sizeof(char **));
7461 }
7462 return n;
7463}
7464
7465INTERCEPTOR(struct __sanitizer_netent *, getnetbyaddr, u32 net, int type) {
7466 void *ctx;
7467 COMMON_INTERCEPTOR_ENTER(ctx, getnetbyaddr, net, type);
7468 struct __sanitizer_netent *n = REAL(getnetbyaddr)(net, type);
7469 if (n) {
7470 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));
7471
7472 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, REAL(strlen)(n->n_name) + 1);
7473
7474 SIZE_T nn_size = 1; // One handles the trailing \0
7475
7476 for (char **nn = n->n_aliases; *nn; ++nn, ++nn_size)
7477 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, REAL(strlen)(*nn) + 1);
7478
7479 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases,
7480 nn_size * sizeof(char **));
7481 }
7482 return n;
7483}
7484#define INIT_NETENT \
7485 COMMON_INTERCEPT_FUNCTION(getnetent); \
7486 COMMON_INTERCEPT_FUNCTION(getnetbyname); \
7487 COMMON_INTERCEPT_FUNCTION(getnetbyaddr)
7488#else
7489#define INIT_NETENT
7490#endif
7491
7492#if SANITIZER_INTERCEPT_GETMNTINFO
7493INTERCEPTOR(int, getmntinfo, void **mntbufp, int flags) {
7494 void *ctx;
7495 COMMON_INTERCEPTOR_ENTER(ctx, getmntinfo, mntbufp, flags);
7496 int cnt = REAL(getmntinfo)(mntbufp, flags);
7497 if (cnt > 0 && mntbufp) {
7498 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mntbufp, sizeof(void *));
7499 if (*mntbufp)
7500#if SANITIZER_NETBSD
7501 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *mntbufp, cnt * struct_statvfs_sz);
7502#else
7503 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *mntbufp, cnt * struct_statfs_sz);
7504#endif
7505 }
7506 return cnt;
7507}
7508#define INIT_GETMNTINFO COMMON_INTERCEPT_FUNCTION(getmntinfo)
7509#else
7510#define INIT_GETMNTINFO
7511#endif
7512
7513#if SANITIZER_INTERCEPT_MI_VECTOR_HASH
7514INTERCEPTOR(void, mi_vector_hash, const void *key, SIZE_T len, u32 seed,
7515 u32 hashes[3]) {
7516 void *ctx;
7517 COMMON_INTERCEPTOR_ENTER(ctx, mi_vector_hash, key, len, seed, hashes);
7518 if (key)
7519 COMMON_INTERCEPTOR_READ_RANGE(ctx, key, len);
7520 REAL(mi_vector_hash)(key, len, seed, hashes);
7521 if (hashes)
7522 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hashes, sizeof(hashes[0]) * 3);
7523}
7524#define INIT_MI_VECTOR_HASH COMMON_INTERCEPT_FUNCTION(mi_vector_hash)
7525#else
7526#define INIT_MI_VECTOR_HASH
7527#endif
7528
7529#if SANITIZER_INTERCEPT_SETVBUF
7530INTERCEPTOR(int, setvbuf, __sanitizer_FILE *stream, char *buf, int mode,
7531 SIZE_T size) {
7532 void *ctx;
7533 COMMON_INTERCEPTOR_ENTER(ctx, setvbuf, stream, buf, mode, size);
7534 int ret = REAL(setvbuf)(stream, buf, mode, size);
7535 if (buf)
7536 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, size);
7537 if (stream)
7538 unpoison_file(stream);
7539 return ret;
7540}
7541
7542INTERCEPTOR(void, setbuf, __sanitizer_FILE *stream, char *buf) {
7543 void *ctx;
7544 COMMON_INTERCEPTOR_ENTER(ctx, setbuf, stream, buf);
7545 REAL(setbuf)(stream, buf);
7546 if (buf) {
7547 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer_bufsiz);
7548 }
7549 if (stream)
7550 unpoison_file(stream);
7551}
7552
7553INTERCEPTOR(void, setbuffer, __sanitizer_FILE *stream, char *buf, int mode) {
7554 void *ctx;
7555 COMMON_INTERCEPTOR_ENTER(ctx, setbuffer, stream, buf, mode);
7556 REAL(setbuffer)(stream, buf, mode);
7557 if (buf) {
7558 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer_bufsiz);
7559 }
7560 if (stream)
7561 unpoison_file(stream);
7562}
7563
7564INTERCEPTOR(void, setlinebuf, __sanitizer_FILE *stream) {
7565 void *ctx;
7566 COMMON_INTERCEPTOR_ENTER(ctx, setlinebuf, stream);
7567 REAL(setlinebuf)(stream);
7568 if (stream)
7569 unpoison_file(stream);
7570}
7571#define INIT_SETVBUF COMMON_INTERCEPT_FUNCTION(setvbuf); \
7572 COMMON_INTERCEPT_FUNCTION(setbuf); \
7573 COMMON_INTERCEPT_FUNCTION(setbuffer); \
7574 COMMON_INTERCEPT_FUNCTION(setlinebuf)
7575#else
7576#define INIT_SETVBUF
7577#endif
7578
7579#if SANITIZER_INTERCEPT_GETVFSSTAT
7580INTERCEPTOR(int, getvfsstat, void *buf, SIZE_T bufsize, int flags) {
7581 void *ctx;
7582 COMMON_INTERCEPTOR_ENTER(ctx, getvfsstat, buf, bufsize, flags);
7583 int ret = REAL(getvfsstat)(buf, bufsize, flags);
7584 if (buf && ret > 0)
7585 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, ret * struct_statvfs_sz);
7586 return ret;
7587}
7588#define INIT_GETVFSSTAT COMMON_INTERCEPT_FUNCTION(getvfsstat)
7589#else
7590#define INIT_GETVFSSTAT
7591#endif
7592
7593#if SANITIZER_INTERCEPT_REGEX
7594INTERCEPTOR(int, regcomp, void *preg, const char *pattern, int cflags) {
7595 void *ctx;
7596 COMMON_INTERCEPTOR_ENTER(ctx, regcomp, preg, pattern, cflags);
7597 if (pattern)
7598 COMMON_INTERCEPTOR_READ_RANGE(ctx, pattern, REAL(strlen)(pattern) + 1);
7599 int res = REAL(regcomp)(preg, pattern, cflags);
7600 if (!res)
7601 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, preg, struct_regex_sz);
7602 return res;
7603}
7604INTERCEPTOR(int, regexec, const void *preg, const char *string, SIZE_T nmatch,
7605 struct __sanitizer_regmatch *pmatch[], int eflags) {
7606 void *ctx;
7607 COMMON_INTERCEPTOR_ENTER(ctx, regexec, preg, string, nmatch, pmatch, eflags);
7608 if (preg)
7609 COMMON_INTERCEPTOR_READ_RANGE(ctx, preg, struct_regex_sz);
7610 if (string)
7611 COMMON_INTERCEPTOR_READ_RANGE(ctx, string, REAL(strlen)(string) + 1);
7612 int res = REAL(regexec)(preg, string, nmatch, pmatch, eflags);
7613 if (!res && pmatch)
7614 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pmatch, nmatch * struct_regmatch_sz);
7615 return res;
7616}
7617INTERCEPTOR(SIZE_T, regerror, int errcode, const void *preg, char *errbuf,
7618 SIZE_T errbuf_size) {
7619 void *ctx;
7620 COMMON_INTERCEPTOR_ENTER(ctx, regerror, errcode, preg, errbuf, errbuf_size);
7621 if (preg)
7622 COMMON_INTERCEPTOR_READ_RANGE(ctx, preg, struct_regex_sz);
7623 SIZE_T res = REAL(regerror)(errcode, preg, errbuf, errbuf_size);
7624 if (errbuf)
7625 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, errbuf, REAL(strlen)(errbuf) + 1);
7626 return res;
7627}
7628INTERCEPTOR(void, regfree, const void *preg) {
7629 void *ctx;
7630 COMMON_INTERCEPTOR_ENTER(ctx, regfree, preg);
7631 if (preg)
7632 COMMON_INTERCEPTOR_READ_RANGE(ctx, preg, struct_regex_sz);
7633 REAL(regfree)(preg);
7634}
7635#define INIT_REGEX \
7636 COMMON_INTERCEPT_FUNCTION(regcomp); \
7637 COMMON_INTERCEPT_FUNCTION(regexec); \
7638 COMMON_INTERCEPT_FUNCTION(regerror); \
7639 COMMON_INTERCEPT_FUNCTION(regfree);
7640#else
7641#define INIT_REGEX
7642#endif
7643
7644#if SANITIZER_INTERCEPT_REGEXSUB
7645INTERCEPTOR(SSIZE_T, regnsub, char *buf, SIZE_T bufsiz, const char *sub,
7646 const struct __sanitizer_regmatch *rm, const char *str) {
7647 void *ctx;
7648 COMMON_INTERCEPTOR_ENTER(ctx, regnsub, buf, bufsiz, sub, rm, str);
7649 if (sub)
7650 COMMON_INTERCEPTOR_READ_RANGE(ctx, sub, REAL(strlen)(sub) + 1);
7651 // The implementation demands and hardcodes 10 elements
7652 if (rm)
7653 COMMON_INTERCEPTOR_READ_RANGE(ctx, rm, 10 * struct_regmatch_sz);
7654 if (str)
7655 COMMON_INTERCEPTOR_READ_RANGE(ctx, str, REAL(strlen)(str) + 1);
7656 SSIZE_T res = REAL(regnsub)(buf, bufsiz, sub, rm, str);
7657 if (res > 0 && buf)
7658 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
7659 return res;
7660}
7661INTERCEPTOR(SSIZE_T, regasub, char **buf, const char *sub,
7662 const struct __sanitizer_regmatch *rm, const char *sstr) {
7663 void *ctx;
7664 COMMON_INTERCEPTOR_ENTER(ctx, regasub, buf, sub, rm, sstr);
7665 if (sub)
7666 COMMON_INTERCEPTOR_READ_RANGE(ctx, sub, REAL(strlen)(sub) + 1);
7667 // Hardcode 10 elements as this is hardcoded size
7668 if (rm)
7669 COMMON_INTERCEPTOR_READ_RANGE(ctx, rm, 10 * struct_regmatch_sz);
7670 if (sstr)
7671 COMMON_INTERCEPTOR_READ_RANGE(ctx, sstr, REAL(strlen)(sstr) + 1);
7672 SSIZE_T res = REAL(regasub)(buf, sub, rm, sstr);
7673 if (res > 0 && buf) {
7674 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sizeof(char *));
7675 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *buf, REAL(strlen)(*buf) + 1);
7676 }
7677 return res;
7678}
7679
7680#define INIT_REGEXSUB \
7681 COMMON_INTERCEPT_FUNCTION(regnsub); \
7682 COMMON_INTERCEPT_FUNCTION(regasub);
7683#else
7684#define INIT_REGEXSUB
7685#endif
7686
7687#if SANITIZER_INTERCEPT_FTS
7688INTERCEPTOR(void *, fts_open, char *const *path_argv, int options,
7689 int (*compar)(void **, void **)) {
7690 void *ctx;
7691 COMMON_INTERCEPTOR_ENTER(ctx, fts_open, path_argv, options, compar);
7692 if (path_argv) {
7693 for (char *const *pa = path_argv; ; ++pa) {
7694 COMMON_INTERCEPTOR_READ_RANGE(ctx, pa, sizeof(char **));
7695 if (!*pa)
7696 break;
7697 COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, REAL(strlen)(*pa) + 1);
7698 }
7699 }
7700 // TODO(kamil): handle compar callback
7701 void *fts = REAL(fts_open)(path_argv, options, compar);
7702 if (fts)
7703 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, fts, struct_FTS_sz);
7704 return fts;
7705}
7706
7707INTERCEPTOR(void *, fts_read, void *ftsp) {
7708 void *ctx;
7709 COMMON_INTERCEPTOR_ENTER(ctx, fts_read, ftsp);
7710 if (ftsp)
7711 COMMON_INTERCEPTOR_READ_RANGE(ctx, ftsp, struct_FTS_sz);
7712 void *ftsent = REAL(fts_read)(ftsp);
7713 if (ftsent)
7714 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ftsent, struct_FTSENT_sz);
7715 return ftsent;
7716}
7717
7718INTERCEPTOR(void *, fts_children, void *ftsp, int options) {
7719 void *ctx;
7720 COMMON_INTERCEPTOR_ENTER(ctx, fts_children, ftsp, options);
7721 if (ftsp)
7722 COMMON_INTERCEPTOR_READ_RANGE(ctx, ftsp, struct_FTS_sz);
7723 void *ftsent = REAL(fts_children)(ftsp, options);
7724 if (ftsent)
7725 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ftsent, struct_FTSENT_sz);
7726 return ftsent;
7727}
7728
7729INTERCEPTOR(int, fts_set, void *ftsp, void *f, int options) {
7730 void *ctx;
7731 COMMON_INTERCEPTOR_ENTER(ctx, fts_set, ftsp, f, options);
7732 if (ftsp)
7733 COMMON_INTERCEPTOR_READ_RANGE(ctx, ftsp, struct_FTS_sz);
7734 if (f)
7735 COMMON_INTERCEPTOR_READ_RANGE(ctx, f, struct_FTSENT_sz);
7736 return REAL(fts_set)(ftsp, f, options);
7737}
7738
7739INTERCEPTOR(int, fts_close, void *ftsp) {
7740 void *ctx;
7741 COMMON_INTERCEPTOR_ENTER(ctx, fts_close, ftsp);
7742 if (ftsp)
7743 COMMON_INTERCEPTOR_READ_RANGE(ctx, ftsp, struct_FTS_sz);
7744 return REAL(fts_close)(ftsp);
7745}
7746#define INIT_FTS \
7747 COMMON_INTERCEPT_FUNCTION(fts_open); \
7748 COMMON_INTERCEPT_FUNCTION(fts_read); \
7749 COMMON_INTERCEPT_FUNCTION(fts_children); \
7750 COMMON_INTERCEPT_FUNCTION(fts_set); \
7751 COMMON_INTERCEPT_FUNCTION(fts_close);
7752#else
7753#define INIT_FTS
7754#endif
7755
7756#if SANITIZER_INTERCEPT_SYSCTL
7757INTERCEPTOR(int, sysctl, int *name, unsigned int namelen, void *oldp,
7758 SIZE_T *oldlenp, void *newp, SIZE_T newlen) {
7759 void *ctx;
7760 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
7761 return internal_sysctl(name, namelen, oldp, oldlenp, newp, newlen);
7762 COMMON_INTERCEPTOR_ENTER(ctx, sysctl, name, namelen, oldp, oldlenp, newp,
7763 newlen);
7764 if (name)
7765 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, namelen * sizeof(*name));
7766 if (oldlenp)
7767 COMMON_INTERCEPTOR_READ_RANGE(ctx, oldlenp, sizeof(*oldlenp));
7768 if (newp && newlen)
7769 COMMON_INTERCEPTOR_READ_RANGE(ctx, newp, newlen);
7770 int res = REAL(sysctl)(name, namelen, oldp, oldlenp, newp, newlen);
7771 if (!res) {
7772 if (oldlenp) {
7773 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldlenp, sizeof(*oldlenp));
7774 if (oldp)
7775 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldp, *oldlenp);
7776 }
7777 }
7778 return res;
7779}
7780
7781INTERCEPTOR(int, sysctlbyname, char *sname, void *oldp, SIZE_T *oldlenp,
7782 void *newp, SIZE_T newlen) {
7783 void *ctx;
7784 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
7785 return internal_sysctlbyname(sname, oldp, oldlenp, newp, newlen);
7786 COMMON_INTERCEPTOR_ENTER(ctx, sysctlbyname, sname, oldp, oldlenp, newp,
7787 newlen);
7788 if (sname)
7789 COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1);
7790 if (oldlenp)
7791 COMMON_INTERCEPTOR_READ_RANGE(ctx, oldlenp, sizeof(*oldlenp));
7792 if (newp && newlen)
7793 COMMON_INTERCEPTOR_READ_RANGE(ctx, newp, newlen);
7794 int res = REAL(sysctlbyname)(sname, oldp, oldlenp, newp, newlen);
7795 if (!res) {
7796 if (oldlenp) {
7797 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldlenp, sizeof(*oldlenp));
7798 if (oldp)
7799 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldp, *oldlenp);
7800 }
7801 }
7802 return res;
7803}
7804
7805INTERCEPTOR(int, sysctlnametomib, const char *sname, int *name,
7806 SIZE_T *namelenp) {
7807 void *ctx;
7808 COMMON_INTERCEPTOR_ENTER(ctx, sysctlnametomib, sname, name, namelenp);
7809 if (sname)
7810 COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1);
7811 if (namelenp)
7812 COMMON_INTERCEPTOR_READ_RANGE(ctx, namelenp, sizeof(*namelenp));
7813 int res = REAL(sysctlnametomib)(sname, name, namelenp);
7814 if (!res) {
7815 if (namelenp) {
7816 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelenp, sizeof(*namelenp));
7817 if (name)
7818 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, *namelenp * sizeof(*name));
7819 }
7820 }
7821 return res;
7822}
7823
7824#define INIT_SYSCTL \
7825 COMMON_INTERCEPT_FUNCTION(sysctl); \
7826 COMMON_INTERCEPT_FUNCTION(sysctlbyname); \
7827 COMMON_INTERCEPT_FUNCTION(sysctlnametomib);
7828#else
7829#define INIT_SYSCTL
7830#endif
7831
7832#if SANITIZER_INTERCEPT_ASYSCTL
7833INTERCEPTOR(void *, asysctl, const int *name, SIZE_T namelen, SIZE_T *len) {
7834 void *ctx;
7835 COMMON_INTERCEPTOR_ENTER(ctx, asysctl, name, namelen, len);
7836 if (name)
7837 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, sizeof(*name) * namelen);
7838 void *res = REAL(asysctl)(name, namelen, len);
7839 if (res && len) {
7840 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, len, sizeof(*len));
7841 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, *len);
7842 }
7843 return res;
7844}
7845
7846INTERCEPTOR(void *, asysctlbyname, const char *sname, SIZE_T *len) {
7847 void *ctx;
7848 COMMON_INTERCEPTOR_ENTER(ctx, asysctlbyname, sname, len);
7849 if (sname)
7850 COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1);
7851 void *res = REAL(asysctlbyname)(sname, len);
7852 if (res && len) {
7853 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, len, sizeof(*len));
7854 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, *len);
7855 }
7856 return res;
7857}
7858#define INIT_ASYSCTL \
7859 COMMON_INTERCEPT_FUNCTION(asysctl); \
7860 COMMON_INTERCEPT_FUNCTION(asysctlbyname);
7861#else
7862#define INIT_ASYSCTL
7863#endif
7864
7865#if SANITIZER_INTERCEPT_SYSCTLGETMIBINFO
7866INTERCEPTOR(int, sysctlgetmibinfo, char *sname, int *name,
7867 unsigned int *namelenp, char *cname, SIZE_T *csz, void **rnode,
7868 int v) {
7869 void *ctx;
7870 COMMON_INTERCEPTOR_ENTER(ctx, sysctlgetmibinfo, sname, name, namelenp, cname,
7871 csz, rnode, v);
7872 if (sname)
7873 COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1);
7874 if (namelenp)
7875 COMMON_INTERCEPTOR_READ_RANGE(ctx, namelenp, sizeof(*namelenp));
7876 if (csz)
7877 COMMON_INTERCEPTOR_READ_RANGE(ctx, csz, sizeof(*csz));
7878 // Skip rnode, it's rarely used and not trivial to sanitize
7879 // It's also used mostly internally
7880 int res = REAL(sysctlgetmibinfo)(sname, name, namelenp, cname, csz, rnode, v);
7881 if (!res) {
7882 if (namelenp) {
7883 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelenp, sizeof(*namelenp));
7884 if (name)
7885 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, *namelenp * sizeof(*name));
7886 }
7887 if (csz) {
7888 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, csz, sizeof(*csz));
7889 if (cname)
7890 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cname, *csz);
7891 }
7892 }
7893 return res;
7894}
7895#define INIT_SYSCTLGETMIBINFO \
7896 COMMON_INTERCEPT_FUNCTION(sysctlgetmibinfo);
7897#else
7898#define INIT_SYSCTLGETMIBINFO
7899#endif
7900
7901#if SANITIZER_INTERCEPT_NL_LANGINFO
7902INTERCEPTOR(char *, nl_langinfo, long item) {
7903 void *ctx;
7904 COMMON_INTERCEPTOR_ENTER(ctx, nl_langinfo, item);
7905 char *ret = REAL(nl_langinfo)(item);
7906 if (ret)
7907 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, REAL(strlen)(ret) + 1);
7908 return ret;
7909}
7910#define INIT_NL_LANGINFO COMMON_INTERCEPT_FUNCTION(nl_langinfo)
7911#else
7912#define INIT_NL_LANGINFO
7913#endif
7914
7915#if SANITIZER_INTERCEPT_MODCTL
7916INTERCEPTOR(int, modctl, int operation, void *argp) {
7917 void *ctx;
7918 int ret;
7919 COMMON_INTERCEPTOR_ENTER(ctx, modctl, operation, argp);
7920
7921 if (operation == modctl_load) {
7922 if (argp) {
7923 __sanitizer_modctl_load_t *ml = (__sanitizer_modctl_load_t *)argp;
7924 COMMON_INTERCEPTOR_READ_RANGE(ctx, ml, sizeof(*ml));
7925 if (ml->ml_filename)
7926 COMMON_INTERCEPTOR_READ_RANGE(ctx, ml->ml_filename,
7927 REAL(strlen)(ml->ml_filename) + 1);
7928 if (ml->ml_props)
7929 COMMON_INTERCEPTOR_READ_RANGE(ctx, ml->ml_props, ml->ml_propslen);
7930 }
7931 ret = REAL(modctl)(operation, argp);
7932 } else if (operation == modctl_unload) {
7933 if (argp) {
7934 const char *name = (const char *)argp;
7935 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
7936 }
7937 ret = REAL(modctl)(operation, argp);
7938 } else if (operation == modctl_stat) {
7939 uptr iov_len;
7940 struct __sanitizer_iovec *iov = (struct __sanitizer_iovec *)argp;
7941 if (iov) {
7942 COMMON_INTERCEPTOR_READ_RANGE(ctx, iov, sizeof(*iov));
7943 iov_len = iov->iov_len;
7944 }
7945 ret = REAL(modctl)(operation, argp);
7946 if (iov)
7947 COMMON_INTERCEPTOR_WRITE_RANGE(
7948 ctx, iov->iov_base, Min(iov_len, iov->iov_len));
7949 } else if (operation == modctl_exists) {
7950 ret = REAL(modctl)(operation, argp);
7951 } else {
7952 ret = REAL(modctl)(operation, argp);
7953 }
7954
7955 return ret;
7956}
7957#define INIT_MODCTL COMMON_INTERCEPT_FUNCTION(modctl)
7958#else
7959#define INIT_MODCTL
7960#endif
7961
7962#if SANITIZER_INTERCEPT_STRTONUM
7963INTERCEPTOR(long long, strtonum, const char *nptr, long long minval,
7964 long long maxval, const char **errstr) {
7965 void *ctx;
7966 COMMON_INTERCEPTOR_ENTER(ctx, strtonum, nptr, minval, maxval, errstr);
7967
7968 // TODO(kamil): Implement strtoll as a common inteceptor
7969 char *real_endptr;
7970 long long ret = (long long)REAL(strtoimax)(nptr, &real_endptr, 10);
7971 StrtolFixAndCheck(ctx, nptr, nullptr, real_endptr, 10);
7972
7973 ret = REAL(strtonum)(nptr, minval, maxval, errstr);
7974 if (errstr) {
7975 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, errstr, sizeof(const char *));
7976 if (*errstr)
7977 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *errstr, REAL(strlen)(*errstr) + 1);
7978 }
7979 return ret;
7980}
7981#define INIT_STRTONUM COMMON_INTERCEPT_FUNCTION(strtonum)
7982#else
7983#define INIT_STRTONUM
7984#endif
7985
7986#if SANITIZER_INTERCEPT_FPARSELN
7987INTERCEPTOR(char *, fparseln, __sanitizer_FILE *stream, SIZE_T *len,
7988 SIZE_T *lineno, const char delim[3], int flags) {
7989 void *ctx;
7990 COMMON_INTERCEPTOR_ENTER(ctx, fparseln, stream, len, lineno, delim, flags);
7991 if (lineno)
7992 COMMON_INTERCEPTOR_READ_RANGE(ctx, lineno, sizeof(*lineno));
7993 if (delim)
7994 COMMON_INTERCEPTOR_READ_RANGE(ctx, delim, sizeof(delim[0]) * 3);
7995 char *ret = REAL(fparseln)(stream, len, lineno, delim, flags);
7996 if (ret) {
7997 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, REAL(strlen)(ret) + 1);
7998 if (len)
7999 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, len, sizeof(*len));
8000 if (lineno)
8001 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lineno, sizeof(*lineno));
8002 }
8003 return ret;
8004}
8005#define INIT_FPARSELN COMMON_INTERCEPT_FUNCTION(fparseln)
8006#else
8007#define INIT_FPARSELN
8008#endif
8009
8010#if SANITIZER_INTERCEPT_STATVFS1
8011INTERCEPTOR(int, statvfs1, const char *path, void *buf, int flags) {
8012 void *ctx;
8013 COMMON_INTERCEPTOR_ENTER(ctx, statvfs1, path, buf, flags);
8014 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
8015 int res = REAL(statvfs1)(path, buf, flags);
8016 if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz);
8017 return res;
8018}
8019INTERCEPTOR(int, fstatvfs1, int fd, void *buf, int flags) {
8020 void *ctx;
8021 COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs1, fd, buf, flags);
8022 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
8023 int res = REAL(fstatvfs1)(fd, buf, flags);
8024 if (!res) {
8025 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz);
8026 if (fd >= 0)
8027 COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
8028 }
8029 return res;
8030}
8031#define INIT_STATVFS1 \
8032 COMMON_INTERCEPT_FUNCTION(statvfs1); \
8033 COMMON_INTERCEPT_FUNCTION(fstatvfs1);
8034#else
8035#define INIT_STATVFS1
8036#endif
8037
8038#if SANITIZER_INTERCEPT_STRTOI
8039INTERCEPTOR(INTMAX_T, strtoi, const char *nptr, char **endptr, int base,
8040 INTMAX_T low, INTMAX_T high, int *rstatus) {
8041 void *ctx;
8042 COMMON_INTERCEPTOR_ENTER(ctx, strtoi, nptr, endptr, base, low, high, rstatus);
8043 char *real_endptr;
8044 INTMAX_T ret = REAL(strtoi)(nptr, &real_endptr, base, low, high, rstatus);
8045 StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
8046 if (rstatus)
8047 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rstatus, sizeof(*rstatus));
8048 return ret;
8049}
8050
8051INTERCEPTOR(UINTMAX_T, strtou, const char *nptr, char **endptr, int base,
8052 UINTMAX_T low, UINTMAX_T high, int *rstatus) {
8053 void *ctx;
8054 COMMON_INTERCEPTOR_ENTER(ctx, strtou, nptr, endptr, base, low, high, rstatus);
8055 char *real_endptr;
8056 UINTMAX_T ret = REAL(strtou)(nptr, &real_endptr, base, low, high, rstatus);
8057 StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
8058 if (rstatus)
8059 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rstatus, sizeof(*rstatus));
8060 return ret;
8061}
8062#define INIT_STRTOI \
8063 COMMON_INTERCEPT_FUNCTION(strtoi); \
8064 COMMON_INTERCEPT_FUNCTION(strtou)
8065#else
8066#define INIT_STRTOI
8067#endif
8068
8069#if SANITIZER_INTERCEPT_CAPSICUM
8070#define CAP_RIGHTS_INIT_INTERCEPTOR(cap_rights_init, rights, ...) \
8071 { \
8072 void *ctx; \
8073 COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_init, rights, ##__VA_ARGS__); \
8074 if (rights) \
8075 COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights)); \
8076 __sanitizer_cap_rights_t *ret = \
8077 REAL(cap_rights_init)(rights, ##__VA_ARGS__); \
8078 if (ret) \
8079 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, sizeof(*ret)); \
8080 return ret; \
8081 }
8082
8083#define CAP_RIGHTS_SET_INTERCEPTOR(cap_rights_set, rights, ...) \
8084 { \
8085 void *ctx; \
8086 COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_set, rights, ##__VA_ARGS__); \
8087 if (rights) \
8088 COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights)); \
8089 __sanitizer_cap_rights_t *ret = \
8090 REAL(cap_rights_set)(rights, ##__VA_ARGS__); \
8091 if (ret) \
8092 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, sizeof(*ret)); \
8093 return ret; \
8094 }
8095
8096#define CAP_RIGHTS_CLEAR_INTERCEPTOR(cap_rights_clear, rights, ...) \
8097 { \
8098 void *ctx; \
8099 COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_clear, rights, ##__VA_ARGS__); \
8100 if (rights) \
8101 COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights)); \
8102 __sanitizer_cap_rights_t *ret = \
8103 REAL(cap_rights_clear)(rights, ##__VA_ARGS__); \
8104 if (ret) \
8105 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, sizeof(*ret)); \
8106 return ret; \
8107 }
8108
8109#define CAP_RIGHTS_IS_SET_INTERCEPTOR(cap_rights_is_set, rights, ...) \
8110 { \
8111 void *ctx; \
8112 COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_is_set, rights, ##__VA_ARGS__); \
8113 if (rights) \
8114 COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights)); \
8115 return REAL(cap_rights_is_set)(rights, ##__VA_ARGS__); \
8116 }
8117
8118INTERCEPTOR(__sanitizer_cap_rights_t *, cap_rights_init,
8119 __sanitizer_cap_rights_t *rights) {
8120 CAP_RIGHTS_INIT_INTERCEPTOR(cap_rights_init, rights);
8121}
8122
8123INTERCEPTOR(__sanitizer_cap_rights_t *, cap_rights_set,
8124 __sanitizer_cap_rights_t *rights) {
8125 CAP_RIGHTS_SET_INTERCEPTOR(cap_rights_set, rights);
8126}
8127
8128INTERCEPTOR(__sanitizer_cap_rights_t *, cap_rights_clear,
8129 __sanitizer_cap_rights_t *rights) {
8130 CAP_RIGHTS_CLEAR_INTERCEPTOR(cap_rights_clear, rights);
8131}
8132
8133INTERCEPTOR(bool, cap_rights_is_set,
8134 __sanitizer_cap_rights_t *rights) {
8135 CAP_RIGHTS_IS_SET_INTERCEPTOR(cap_rights_is_set, rights);
8136}
8137
8138INTERCEPTOR(int, cap_rights_limit, int fd,
8139 const __sanitizer_cap_rights_t *rights) {
8140 void *ctx;
8141 COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_limit, fd, rights);
8142 if (rights)
8143 COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights));
8144
8145 return REAL(cap_rights_limit)(fd, rights);
8146}
8147
8148INTERCEPTOR(int, cap_rights_get, int fd, __sanitizer_cap_rights_t *rights) {
8149 void *ctx;
8150 COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_get, fd, rights);
8151 int ret = REAL(cap_rights_get)(fd, rights);
8152 if (!ret && rights)
8153 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rights, sizeof(*rights));
8154
8155 return ret;
8156}
8157
8158INTERCEPTOR(bool, cap_rights_is_valid, const __sanitizer_cap_rights_t *rights) {
8159 void *ctx;
8160 COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_is_valid, rights);
8161 if (rights)
8162 COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights));
8163
8164 return REAL(cap_rights_is_valid(rights));
8165}
8166
8167INTERCEPTOR(__sanitizer_cap_rights *, cap_rights_merge,
8168 __sanitizer_cap_rights *dst, const __sanitizer_cap_rights *src) {
8169 void *ctx;
8170 COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_merge, dst, src);
8171 if (src)
8172 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
8173
8174 __sanitizer_cap_rights *ret = REAL(cap_rights_merge)(dst, src);
8175 if (dst)
8176 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(*dst));
8177
8178 return ret;
8179}
8180
8181INTERCEPTOR(__sanitizer_cap_rights *, cap_rights_remove,
8182 __sanitizer_cap_rights *dst, const __sanitizer_cap_rights *src) {
8183 void *ctx;
8184 COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_remove, dst, src);
8185 if (src)
8186 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
8187
8188 __sanitizer_cap_rights *ret = REAL(cap_rights_remove)(dst, src);
8189 if (dst)
8190 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(*dst));
8191
8192 return ret;
8193}
8194
8195INTERCEPTOR(bool, cap_rights_contains, const __sanitizer_cap_rights *big,
8196 const __sanitizer_cap_rights *little) {
8197 void *ctx;
8198 COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_contains, big, little);
8199 if (little)
8200 COMMON_INTERCEPTOR_READ_RANGE(ctx, little, sizeof(*little));
8201 if (big)
8202 COMMON_INTERCEPTOR_READ_RANGE(ctx, big, sizeof(*big));
8203
8204 return REAL(cap_rights_contains)(big, little);
8205}
8206
8207INTERCEPTOR(int, cap_ioctls_limit, int fd, const uptr *cmds, SIZE_T ncmds) {
8208 void *ctx;
8209 COMMON_INTERCEPTOR_ENTER(ctx, cap_ioctls_limit, fd, cmds, ncmds);
8210 if (cmds)
8211 COMMON_INTERCEPTOR_READ_RANGE(ctx, cmds, sizeof(*cmds) * ncmds);
8212
8213 return REAL(cap_ioctls_limit)(fd, cmds, ncmds);
8214}
8215
8216INTERCEPTOR(int, cap_ioctls_get, int fd, uptr *cmds, SIZE_T maxcmds) {
8217 void *ctx;
8218 COMMON_INTERCEPTOR_ENTER(ctx, cap_ioctls_get, fd, cmds, maxcmds);
8219 int ret = REAL(cap_ioctls_get)(fd, cmds, maxcmds);
8220 if (!ret && cmds)
8221 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cmds, sizeof(*cmds) * maxcmds);
8222
8223 return ret;
8224}
8225#define INIT_CAPSICUM \
8226 COMMON_INTERCEPT_FUNCTION(cap_rights_init); \
8227 COMMON_INTERCEPT_FUNCTION(cap_rights_set); \
8228 COMMON_INTERCEPT_FUNCTION(cap_rights_clear); \
8229 COMMON_INTERCEPT_FUNCTION(cap_rights_is_set); \
8230 COMMON_INTERCEPT_FUNCTION(cap_rights_get); \
8231 COMMON_INTERCEPT_FUNCTION(cap_rights_limit); \
8232 COMMON_INTERCEPT_FUNCTION(cap_rights_contains); \
8233 COMMON_INTERCEPT_FUNCTION(cap_rights_remove); \
8234 COMMON_INTERCEPT_FUNCTION(cap_rights_merge); \
8235 COMMON_INTERCEPT_FUNCTION(cap_rights_is_valid); \
8236 COMMON_INTERCEPT_FUNCTION(cap_ioctls_get); \
8237 COMMON_INTERCEPT_FUNCTION(cap_ioctls_limit)
8238#else
8239#define INIT_CAPSICUM
8240#endif
8241
8242#if SANITIZER_INTERCEPT_SHA1
8243INTERCEPTOR(void, SHA1Init, void *context) {
8244 void *ctx;
8245 COMMON_INTERCEPTOR_ENTER(ctx, SHA1Init, context);
8246 REAL(SHA1Init)(context);
8247 if (context)
8248 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, SHA1_CTX_sz);
8249}
8250INTERCEPTOR(void, SHA1Update, void *context, const u8 *data, unsigned len) {
8251 void *ctx;
8252 COMMON_INTERCEPTOR_ENTER(ctx, SHA1Update, context, data, len);
8253 if (data && len > 0)
8254 COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
8255 if (context)
8256 COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA1_CTX_sz);
8257 REAL(SHA1Update)(context, data, len);
8258 if (context)
8259 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, SHA1_CTX_sz);
8260}
8261INTERCEPTOR(void, SHA1Final, u8 digest[20], void *context) {
8262 void *ctx;
8263 COMMON_INTERCEPTOR_ENTER(ctx, SHA1Final, digest, context);
8264 if (context)
8265 COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA1_CTX_sz);
8266 REAL(SHA1Final)(digest, context);
8267 if (digest)
8268 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(u8) * 20);
8269}
8270INTERCEPTOR(void, SHA1Transform, u32 state[5], u8 buffer[64]) {
8271 void *ctx;
8272 COMMON_INTERCEPTOR_ENTER(ctx, SHA1Transform, state, buffer);
8273 if (state)
8274 COMMON_INTERCEPTOR_READ_RANGE(ctx, state, sizeof(u32) * 5);
8275 if (buffer)
8276 COMMON_INTERCEPTOR_READ_RANGE(ctx, buffer, sizeof(u8) * 64);
8277 REAL(SHA1Transform)(state, buffer);
8278 if (state)
8279 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, state, sizeof(u32) * 5);
8280}
8281INTERCEPTOR(char *, SHA1End, void *context, char *buf) {
8282 void *ctx;
8283 COMMON_INTERCEPTOR_ENTER(ctx, SHA1End, context, buf);
8284 if (context)
8285 COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA1_CTX_sz);
8286 char *ret = REAL(SHA1End)(context, buf);
8287 if (ret)
8288 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length);
8289 return ret;
8290}
8291INTERCEPTOR(char *, SHA1File, char *filename, char *buf) {
8292 void *ctx;
8293 COMMON_INTERCEPTOR_ENTER(ctx, SHA1File, filename, buf);
8294 if (filename)
8295 COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
8296 char *ret = REAL(SHA1File)(filename, buf);
8297 if (ret)
8298 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length);
8299 return ret;
8300}
8301INTERCEPTOR(char *, SHA1FileChunk, char *filename, char *buf, OFF_T offset,
8302 OFF_T length) {
8303 void *ctx;
8304 COMMON_INTERCEPTOR_ENTER(ctx, SHA1FileChunk, filename, buf, offset, length);
8305 if (filename)
8306 COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
8307 char *ret = REAL(SHA1FileChunk)(filename, buf, offset, length);
8308 if (ret)
8309 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length);
8310 return ret;
8311}
8312INTERCEPTOR(char *, SHA1Data, u8 *data, SIZE_T len, char *buf) {
8313 void *ctx;
8314 COMMON_INTERCEPTOR_ENTER(ctx, SHA1Data, data, len, buf);
8315 if (data)
8316 COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
8317 char *ret = REAL(SHA1Data)(data, len, buf);
8318 if (ret)
8319 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length);
8320 return ret;
8321}
8322#define INIT_SHA1 \
8323 COMMON_INTERCEPT_FUNCTION(SHA1Init); \
8324 COMMON_INTERCEPT_FUNCTION(SHA1Update); \
8325 COMMON_INTERCEPT_FUNCTION(SHA1Final); \
8326 COMMON_INTERCEPT_FUNCTION(SHA1Transform); \
8327 COMMON_INTERCEPT_FUNCTION(SHA1End); \
8328 COMMON_INTERCEPT_FUNCTION(SHA1File); \
8329 COMMON_INTERCEPT_FUNCTION(SHA1FileChunk); \
8330 COMMON_INTERCEPT_FUNCTION(SHA1Data)
8331#else
8332#define INIT_SHA1
8333#endif
8334
8335#if SANITIZER_INTERCEPT_MD4
8336INTERCEPTOR(void, MD4Init, void *context) {
8337 void *ctx;
8338 COMMON_INTERCEPTOR_ENTER(ctx, MD4Init, context);
8339 REAL(MD4Init)(context);
8340 if (context)
8341 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD4_CTX_sz);
8342}
8343
8344INTERCEPTOR(void, MD4Update, void *context, const unsigned char *data,
8345 unsigned int len) {
8346 void *ctx;
8347 COMMON_INTERCEPTOR_ENTER(ctx, MD4Update, context, data, len);
8348 if (data && len > 0)
8349 COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
8350 if (context)
8351 COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD4_CTX_sz);
8352 REAL(MD4Update)(context, data, len);
8353 if (context)
8354 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD4_CTX_sz);
8355}
8356
8357INTERCEPTOR(void, MD4Final, unsigned char digest[16], void *context) {
8358 void *ctx;
8359 COMMON_INTERCEPTOR_ENTER(ctx, MD4Final, digest, context);
8360 if (context)
8361 COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD4_CTX_sz);
8362 REAL(MD4Final)(digest, context);
8363 if (digest)
8364 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(unsigned char) * 16);
8365}
8366
8367INTERCEPTOR(char *, MD4End, void *context, char *buf) {
8368 void *ctx;
8369 COMMON_INTERCEPTOR_ENTER(ctx, MD4End, context, buf);
8370 if (context)
8371 COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD4_CTX_sz);
8372 char *ret = REAL(MD4End)(context, buf);
8373 if (ret)
8374 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD4_return_length);
8375 return ret;
8376}
8377
8378INTERCEPTOR(char *, MD4File, const char *filename, char *buf) {
8379 void *ctx;
8380 COMMON_INTERCEPTOR_ENTER(ctx, MD4File, filename, buf);
8381 if (filename)
8382 COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
8383 char *ret = REAL(MD4File)(filename, buf);
8384 if (ret)
8385 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD4_return_length);
8386 return ret;
8387}
8388
8389INTERCEPTOR(char *, MD4Data, const unsigned char *data, unsigned int len,
8390 char *buf) {
8391 void *ctx;
8392 COMMON_INTERCEPTOR_ENTER(ctx, MD4Data, data, len, buf);
8393 if (data && len > 0)
8394 COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
8395 char *ret = REAL(MD4Data)(data, len, buf);
8396 if (ret)
8397 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD4_return_length);
8398 return ret;
8399}
8400
8401#define INIT_MD4 \
8402 COMMON_INTERCEPT_FUNCTION(MD4Init); \
8403 COMMON_INTERCEPT_FUNCTION(MD4Update); \
8404 COMMON_INTERCEPT_FUNCTION(MD4Final); \
8405 COMMON_INTERCEPT_FUNCTION(MD4End); \
8406 COMMON_INTERCEPT_FUNCTION(MD4File); \
8407 COMMON_INTERCEPT_FUNCTION(MD4Data)
8408#else
8409#define INIT_MD4
8410#endif
8411
8412#if SANITIZER_INTERCEPT_RMD160
8413INTERCEPTOR(void, RMD160Init, void *context) {
8414 void *ctx;
8415 COMMON_INTERCEPTOR_ENTER(ctx, RMD160Init, context);
8416 REAL(RMD160Init)(context);
8417 if (context)
8418 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, RMD160_CTX_sz);
8419}
8420INTERCEPTOR(void, RMD160Update, void *context, const u8 *data, unsigned len) {
8421 void *ctx;
8422 COMMON_INTERCEPTOR_ENTER(ctx, RMD160Update, context, data, len);
8423 if (data && len > 0)
8424 COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
8425 if (context)
8426 COMMON_INTERCEPTOR_READ_RANGE(ctx, context, RMD160_CTX_sz);
8427 REAL(RMD160Update)(context, data, len);
8428 if (context)
8429 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, RMD160_CTX_sz);
8430}
8431INTERCEPTOR(void, RMD160Final, u8 digest[20], void *context) {
8432 void *ctx;
8433 COMMON_INTERCEPTOR_ENTER(ctx, RMD160Final, digest, context);
8434 if (context)
8435 COMMON_INTERCEPTOR_READ_RANGE(ctx, context, RMD160_CTX_sz);
8436 REAL(RMD160Final)(digest, context);
8437 if (digest)
8438 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(u8) * 20);
8439}
8440INTERCEPTOR(void, RMD160Transform, u32 state[5], u16 buffer[16]) {
8441 void *ctx;
8442 COMMON_INTERCEPTOR_ENTER(ctx, RMD160Transform, state, buffer);
8443 if (state)
8444 COMMON_INTERCEPTOR_READ_RANGE(ctx, state, sizeof(u32) * 5);
8445 if (buffer)
8446 COMMON_INTERCEPTOR_READ_RANGE(ctx, buffer, sizeof(u32) * 16);
8447 REAL(RMD160Transform)(state, buffer);
8448 if (state)
8449 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, state, sizeof(u32) * 5);
8450}
8451INTERCEPTOR(char *, RMD160End, void *context, char *buf) {
8452 void *ctx;
8453 COMMON_INTERCEPTOR_ENTER(ctx, RMD160End, context, buf);
8454 if (context)
8455 COMMON_INTERCEPTOR_READ_RANGE(ctx, context, RMD160_CTX_sz);
8456 char *ret = REAL(RMD160End)(context, buf);
8457 if (ret)
8458 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, RMD160_return_length);
8459 return ret;
8460}
8461INTERCEPTOR(char *, RMD160File, char *filename, char *buf) {
8462 void *ctx;
8463 COMMON_INTERCEPTOR_ENTER(ctx, RMD160File, filename, buf);
8464 if (filename)
8465 COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
8466 char *ret = REAL(RMD160File)(filename, buf);
8467 if (ret)
8468 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, RMD160_return_length);
8469 return ret;
8470}
8471INTERCEPTOR(char *, RMD160FileChunk, char *filename, char *buf, OFF_T offset,
8472 OFF_T length) {
8473 void *ctx;
8474 COMMON_INTERCEPTOR_ENTER(ctx, RMD160FileChunk, filename, buf, offset, length);
8475 if (filename)
8476 COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
8477 char *ret = REAL(RMD160FileChunk)(filename, buf, offset, length);
8478 if (ret)
8479 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, RMD160_return_length);
8480 return ret;
8481}
8482INTERCEPTOR(char *, RMD160Data, u8 *data, SIZE_T len, char *buf) {
8483 void *ctx;
8484 COMMON_INTERCEPTOR_ENTER(ctx, RMD160Data, data, len, buf);
8485 if (data && len > 0)
8486 COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
8487 char *ret = REAL(RMD160Data)(data, len, buf);
8488 if (ret)
8489 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, RMD160_return_length);
8490 return ret;
8491}
8492#define INIT_RMD160 \
8493 COMMON_INTERCEPT_FUNCTION(RMD160Init); \
8494 COMMON_INTERCEPT_FUNCTION(RMD160Update); \
8495 COMMON_INTERCEPT_FUNCTION(RMD160Final); \
8496 COMMON_INTERCEPT_FUNCTION(RMD160Transform); \
8497 COMMON_INTERCEPT_FUNCTION(RMD160End); \
8498 COMMON_INTERCEPT_FUNCTION(RMD160File); \
8499 COMMON_INTERCEPT_FUNCTION(RMD160FileChunk); \
8500 COMMON_INTERCEPT_FUNCTION(RMD160Data)
8501#else
8502#define INIT_RMD160
8503#endif
8504
8505#if SANITIZER_INTERCEPT_MD5
8506INTERCEPTOR(void, MD5Init, void *context) {
8507 void *ctx;
8508 COMMON_INTERCEPTOR_ENTER(ctx, MD5Init, context);
8509 REAL(MD5Init)(context);
8510 if (context)
8511 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD5_CTX_sz);
8512}
8513
8514INTERCEPTOR(void, MD5Update, void *context, const unsigned char *data,
8515 unsigned int len) {
8516 void *ctx;
8517 COMMON_INTERCEPTOR_ENTER(ctx, MD5Update, context, data, len);
8518 if (data && len > 0)
8519 COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
8520 if (context)
8521 COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD5_CTX_sz);
8522 REAL(MD5Update)(context, data, len);
8523 if (context)
8524 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD5_CTX_sz);
8525}
8526
8527INTERCEPTOR(void, MD5Final, unsigned char digest[16], void *context) {
8528 void *ctx;
8529 COMMON_INTERCEPTOR_ENTER(ctx, MD5Final, digest, context);
8530 if (context)
8531 COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD5_CTX_sz);
8532 REAL(MD5Final)(digest, context);
8533 if (digest)
8534 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(unsigned char) * 16);
8535}
8536
8537INTERCEPTOR(char *, MD5End, void *context, char *buf) {
8538 void *ctx;
8539 COMMON_INTERCEPTOR_ENTER(ctx, MD5End, context, buf);
8540 if (context)
8541 COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD5_CTX_sz);
8542 char *ret = REAL(MD5End)(context, buf);
8543 if (ret)
8544 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD5_return_length);
8545 return ret;
8546}
8547
8548INTERCEPTOR(char *, MD5File, const char *filename, char *buf) {
8549 void *ctx;
8550 COMMON_INTERCEPTOR_ENTER(ctx, MD5File, filename, buf);
8551 if (filename)
8552 COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
8553 char *ret = REAL(MD5File)(filename, buf);
8554 if (ret)
8555 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD5_return_length);
8556 return ret;
8557}
8558
8559INTERCEPTOR(char *, MD5Data, const unsigned char *data, unsigned int len,
8560 char *buf) {
8561 void *ctx;
8562 COMMON_INTERCEPTOR_ENTER(ctx, MD5Data, data, len, buf);
8563 if (data && len > 0)
8564 COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
8565 char *ret = REAL(MD5Data)(data, len, buf);
8566 if (ret)
8567 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD5_return_length);
8568 return ret;
8569}
8570
8571#define INIT_MD5 \
8572 COMMON_INTERCEPT_FUNCTION(MD5Init); \
8573 COMMON_INTERCEPT_FUNCTION(MD5Update); \
8574 COMMON_INTERCEPT_FUNCTION(MD5Final); \
8575 COMMON_INTERCEPT_FUNCTION(MD5End); \
8576 COMMON_INTERCEPT_FUNCTION(MD5File); \
8577 COMMON_INTERCEPT_FUNCTION(MD5Data)
8578#else
8579#define INIT_MD5
8580#endif
8581
8582#if SANITIZER_INTERCEPT_FSEEK
8583INTERCEPTOR(int, fseek, __sanitizer_FILE *stream, long int offset, int whence) {
8584 void *ctx;
8585 COMMON_INTERCEPTOR_ENTER(ctx, fseek, stream, offset, whence);
8586 return REAL(fseek)(stream, offset, whence);
8587}
8588INTERCEPTOR(int, fseeko, __sanitizer_FILE *stream, OFF_T offset, int whence) {
8589 void *ctx;
8590 COMMON_INTERCEPTOR_ENTER(ctx, fseeko, stream, offset, whence);
8591 return REAL(fseeko)(stream, offset, whence);
8592}
8593INTERCEPTOR(long int, ftell, __sanitizer_FILE *stream) {
8594 void *ctx;
8595 COMMON_INTERCEPTOR_ENTER(ctx, ftell, stream);
8596 return REAL(ftell)(stream);
8597}
8598INTERCEPTOR(OFF_T, ftello, __sanitizer_FILE *stream) {
8599 void *ctx;
8600 COMMON_INTERCEPTOR_ENTER(ctx, ftello, stream);
8601 return REAL(ftello)(stream);
8602}
8603INTERCEPTOR(void, rewind, __sanitizer_FILE *stream) {
8604 void *ctx;
8605 COMMON_INTERCEPTOR_ENTER(ctx, rewind, stream);
8606 return REAL(rewind)(stream);
8607}
8608INTERCEPTOR(int, fgetpos, __sanitizer_FILE *stream, void *pos) {
8609 void *ctx;
8610 COMMON_INTERCEPTOR_ENTER(ctx, fgetpos, stream, pos);
8611 int ret = REAL(fgetpos)(stream, pos);
8612 if (pos && !ret)
8613 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pos, fpos_t_sz);
8614 return ret;
8615}
8616INTERCEPTOR(int, fsetpos, __sanitizer_FILE *stream, const void *pos) {
8617 void *ctx;
8618 COMMON_INTERCEPTOR_ENTER(ctx, fsetpos, stream, pos);
8619 if (pos)
8620 COMMON_INTERCEPTOR_READ_RANGE(ctx, pos, fpos_t_sz);
8621 return REAL(fsetpos)(stream, pos);
8622}
8623#define INIT_FSEEK \
8624 COMMON_INTERCEPT_FUNCTION(fseek); \
8625 COMMON_INTERCEPT_FUNCTION(fseeko); \
8626 COMMON_INTERCEPT_FUNCTION(ftell); \
8627 COMMON_INTERCEPT_FUNCTION(ftello); \
8628 COMMON_INTERCEPT_FUNCTION(rewind); \
8629 COMMON_INTERCEPT_FUNCTION(fgetpos); \
8630 COMMON_INTERCEPT_FUNCTION(fsetpos)
8631#else
8632#define INIT_FSEEK
8633#endif
8634
8635#if SANITIZER_INTERCEPT_MD2
8636INTERCEPTOR(void, MD2Init, void *context) {
8637 void *ctx;
8638 COMMON_INTERCEPTOR_ENTER(ctx, MD2Init, context);
8639 REAL(MD2Init)(context);
8640 if (context)
8641 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD2_CTX_sz);
8642}
8643
8644INTERCEPTOR(void, MD2Update, void *context, const unsigned char *data,
8645 unsigned int len) {
8646 void *ctx;
8647 COMMON_INTERCEPTOR_ENTER(ctx, MD2Update, context, data, len);
8648 if (data && len > 0)
8649 COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
8650 if (context)
8651 COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD2_CTX_sz);
8652 REAL(MD2Update)(context, data, len);
8653 if (context)
8654 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD2_CTX_sz);
8655}
8656
8657INTERCEPTOR(void, MD2Final, unsigned char digest[16], void *context) {
8658 void *ctx;
8659 COMMON_INTERCEPTOR_ENTER(ctx, MD2Final, digest, context);
8660 if (context)
8661 COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD2_CTX_sz);
8662 REAL(MD2Final)(digest, context);
8663 if (digest)
8664 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(unsigned char) * 16);
8665}
8666
8667INTERCEPTOR(char *, MD2End, void *context, char *buf) {
8668 void *ctx;
8669 COMMON_INTERCEPTOR_ENTER(ctx, MD2End, context, buf);
8670 if (context)
8671 COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD2_CTX_sz);
8672 char *ret = REAL(MD2End)(context, buf);
8673 if (ret)
8674 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD2_return_length);
8675 return ret;
8676}
8677
8678INTERCEPTOR(char *, MD2File, const char *filename, char *buf) {
8679 void *ctx;
8680 COMMON_INTERCEPTOR_ENTER(ctx, MD2File, filename, buf);
8681 if (filename)
8682 COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);
8683 char *ret = REAL(MD2File)(filename, buf);
8684 if (ret)
8685 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD2_return_length);
8686 return ret;
8687}
8688
8689INTERCEPTOR(char *, MD2Data, const unsigned char *data, unsigned int len,
8690 char *buf) {
8691 void *ctx;
8692 COMMON_INTERCEPTOR_ENTER(ctx, MD2Data, data, len, buf);
8693 if (data && len > 0)
8694 COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
8695 char *ret = REAL(MD2Data)(data, len, buf);
8696 if (ret)
8697 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD2_return_length);
8698 return ret;
8699}
8700
8701#define INIT_MD2 \
8702 COMMON_INTERCEPT_FUNCTION(MD2Init); \
8703 COMMON_INTERCEPT_FUNCTION(MD2Update); \
8704 COMMON_INTERCEPT_FUNCTION(MD2Final); \
8705 COMMON_INTERCEPT_FUNCTION(MD2End); \
8706 COMMON_INTERCEPT_FUNCTION(MD2File); \
8707 COMMON_INTERCEPT_FUNCTION(MD2Data)
8708#else
8709#define INIT_MD2
8710#endif
8711
8712#if SANITIZER_INTERCEPT_SHA2
8713#define SHA2_INTERCEPTORS(LEN, SHA2_STATE_T) \
8714 INTERCEPTOR(void, SHA##LEN##_Init, void *context) { \
8715 void *ctx; \
8716 COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_Init, context); \
8717 REAL(SHA##LEN##_Init)(context); \
8718 if (context) \
8719 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
8720 } \
8721 INTERCEPTOR(void, SHA##LEN##_Update, void *context, \
8722 const u8 *data, SIZE_T len) { \
8723 void *ctx; \
8724 COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_Update, context, data, len); \
8725 if (data && len > 0) \
8726 COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len); \
8727 if (context) \
8728 COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
8729 REAL(SHA##LEN##_Update)(context, data, len); \
8730 if (context) \
8731 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
8732 } \
8733 INTERCEPTOR(void, SHA##LEN##_Final, u8 digest[LEN/8], \
8734 void *context) { \
8735 void *ctx; \
8736 CHECK_EQ(SHA##LEN##_digest_length, LEN/8); \
8737 COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_Final, digest, context); \
8738 if (context) \
8739 COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
8740 REAL(SHA##LEN##_Final)(digest, context); \
8741 if (digest) \
8742 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, \
8743 sizeof(digest[0]) * \
8744 SHA##LEN##_digest_length); \
8745 } \
8746 INTERCEPTOR(char *, SHA##LEN##_End, void *context, char *buf) { \
8747 void *ctx; \
8748 COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_End, context, buf); \
8749 if (context) \
8750 COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
8751 char *ret = REAL(SHA##LEN##_End)(context, buf); \
8752 if (ret) \
8753 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \
8754 return ret; \
8755 } \
8756 INTERCEPTOR(char *, SHA##LEN##_File, const char *filename, char *buf) { \
8757 void *ctx; \
8758 COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_File, filename, buf); \
8759 if (filename) \
8760 COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);\
8761 char *ret = REAL(SHA##LEN##_File)(filename, buf); \
8762 if (ret) \
8763 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \
8764 return ret; \
8765 } \
8766 INTERCEPTOR(char *, SHA##LEN##_FileChunk, const char *filename, char *buf, \
8767 OFF_T offset, OFF_T length) { \
8768 void *ctx; \
8769 COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_FileChunk, filename, buf, offset, \
8770 length); \
8771 if (filename) \
8772 COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, REAL(strlen)(filename) + 1);\
8773 char *ret = REAL(SHA##LEN##_FileChunk)(filename, buf, offset, length); \
8774 if (ret) \
8775 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \
8776 return ret; \
8777 } \
8778 INTERCEPTOR(char *, SHA##LEN##_Data, u8 *data, SIZE_T len, char *buf) { \
8779 void *ctx; \
8780 COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_Data, data, len, buf); \
8781 if (data && len > 0) \
8782 COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len); \
8783 char *ret = REAL(SHA##LEN##_Data)(data, len, buf); \
8784 if (ret) \
8785 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \
8786 return ret; \
8787 }
8788
8789SHA2_INTERCEPTORS(224, u32);
8790SHA2_INTERCEPTORS(256, u32);
8791SHA2_INTERCEPTORS(384, u64);
8792SHA2_INTERCEPTORS(512, u64);
8793
8794#define INIT_SHA2_INTECEPTORS(LEN) \
8795 COMMON_INTERCEPT_FUNCTION(SHA##LEN##_Init); \
8796 COMMON_INTERCEPT_FUNCTION(SHA##LEN##_Update); \
8797 COMMON_INTERCEPT_FUNCTION(SHA##LEN##_Final); \
8798 COMMON_INTERCEPT_FUNCTION(SHA##LEN##_End); \
8799 COMMON_INTERCEPT_FUNCTION(SHA##LEN##_File); \
8800 COMMON_INTERCEPT_FUNCTION(SHA##LEN##_FileChunk); \
8801 COMMON_INTERCEPT_FUNCTION(SHA##LEN##_Data)
8802
8803#define INIT_SHA2 \
8804 INIT_SHA2_INTECEPTORS(224); \
8805 INIT_SHA2_INTECEPTORS(256); \
8806 INIT_SHA2_INTECEPTORS(384); \
8807 INIT_SHA2_INTECEPTORS(512)
8808#undef SHA2_INTERCEPTORS
8809#else
8810#define INIT_SHA2
8811#endif
8812
8813#if SANITIZER_INTERCEPT_VIS
8814INTERCEPTOR(char *, vis, char *dst, int c, int flag, int nextc) {
8815 void *ctx;
8816 COMMON_INTERCEPTOR_ENTER(ctx, vis, dst, c, flag, nextc);
8817 char *end = REAL(vis)(dst, c, flag, nextc);
8818 // dst is NULL terminated and end points to the NULL char
8819 if (dst && end)
8820 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, end - dst + 1);
8821 return end;
8822}
8823INTERCEPTOR(char *, nvis, char *dst, SIZE_T dlen, int c, int flag, int nextc) {
8824 void *ctx;
8825 COMMON_INTERCEPTOR_ENTER(ctx, nvis, dst, dlen, c, flag, nextc);
8826 char *end = REAL(nvis)(dst, dlen, c, flag, nextc);
8827 // nvis cannot make sure the dst is NULL terminated
8828 if (dst && end)
8829 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, end - dst + 1);
8830 return end;
8831}
8832INTERCEPTOR(int, strvis, char *dst, const char *src, int flag) {
8833 void *ctx;
8834 COMMON_INTERCEPTOR_ENTER(ctx, strvis, dst, src, flag);
8835 if (src)
8836 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
8837 int len = REAL(strvis)(dst, src, flag);
8838 if (dst)
8839 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1);
8840 return len;
8841}
8842INTERCEPTOR(int, stravis, char **dst, const char *src, int flag) {
8843 void *ctx;
8844 COMMON_INTERCEPTOR_ENTER(ctx, stravis, dst, src, flag);
8845 if (src)
8846 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
8847 int len = REAL(stravis)(dst, src, flag);
8848 if (dst) {
8849 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(char *));
8850 if (*dst)
8851 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *dst, len + 1);
8852 }
8853 return len;
8854}
8855INTERCEPTOR(int, strnvis, char *dst, SIZE_T dlen, const char *src, int flag) {
8856 void *ctx;
8857 COMMON_INTERCEPTOR_ENTER(ctx, strnvis, dst, dlen, src, flag);
8858 if (src)
8859 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
8860 int len = REAL(strnvis)(dst, dlen, src, flag);
8861 // The interface will be valid even if there is no space for NULL char
8862 if (dst && len > 0)
8863 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1);
8864 return len;
8865}
8866INTERCEPTOR(int, strvisx, char *dst, const char *src, SIZE_T len, int flag) {
8867 void *ctx;
8868 COMMON_INTERCEPTOR_ENTER(ctx, strvisx, dst, src, len, flag);
8869 if (src)
8870 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
8871 int ret = REAL(strvisx)(dst, src, len, flag);
8872 if (dst)
8873 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
8874 return ret;
8875}
8876INTERCEPTOR(int, strnvisx, char *dst, SIZE_T dlen, const char *src, SIZE_T len,
8877 int flag) {
8878 void *ctx;
8879 COMMON_INTERCEPTOR_ENTER(ctx, strnvisx, dst, dlen, src, len, flag);
8880 if (src)
8881 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
8882 int ret = REAL(strnvisx)(dst, dlen, src, len, flag);
8883 if (dst && ret >= 0)
8884 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
8885 return ret;
8886}
8887INTERCEPTOR(int, strenvisx, char *dst, SIZE_T dlen, const char *src, SIZE_T len,
8888 int flag, int *cerr_ptr) {
8889 void *ctx;
8890 COMMON_INTERCEPTOR_ENTER(ctx, strenvisx, dst, dlen, src, len, flag, cerr_ptr);
8891 if (src)
8892 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
8893 // FIXME: only need to be checked when "flag | VIS_NOLOCALE" doesn't hold
8894 // according to the implementation
8895 if (cerr_ptr)
8896 COMMON_INTERCEPTOR_READ_RANGE(ctx, cerr_ptr, sizeof(int));
8897 int ret = REAL(strenvisx)(dst, dlen, src, len, flag, cerr_ptr);
8898 if (dst && ret >= 0)
8899 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
8900 if (cerr_ptr)
8901 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cerr_ptr, sizeof(int));
8902 return ret;
8903}
8904INTERCEPTOR(char *, svis, char *dst, int c, int flag, int nextc,
8905 const char *extra) {
8906 void *ctx;
8907 COMMON_INTERCEPTOR_ENTER(ctx, svis, dst, c, flag, nextc, extra);
8908 if (extra)
8909 COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
8910 char *end = REAL(svis)(dst, c, flag, nextc, extra);
8911 if (dst && end)
8912 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, end - dst + 1);
8913 return end;
8914}
8915INTERCEPTOR(char *, snvis, char *dst, SIZE_T dlen, int c, int flag, int nextc,
8916 const char *extra) {
8917 void *ctx;
8918 COMMON_INTERCEPTOR_ENTER(ctx, snvis, dst, dlen, c, flag, nextc, extra);
8919 if (extra)
8920 COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
8921 char *end = REAL(snvis)(dst, dlen, c, flag, nextc, extra);
8922 if (dst && end)
8923 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst,
8924 Min((SIZE_T)(end - dst + 1), dlen));
8925 return end;
8926}
8927INTERCEPTOR(int, strsvis, char *dst, const char *src, int flag,
8928 const char *extra) {
8929 void *ctx;
8930 COMMON_INTERCEPTOR_ENTER(ctx, strsvis, dst, src, flag, extra);
8931 if (src)
8932 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
8933 if (extra)
8934 COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
8935 int len = REAL(strsvis)(dst, src, flag, extra);
8936 if (dst)
8937 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1);
8938 return len;
8939}
8940INTERCEPTOR(int, strsnvis, char *dst, SIZE_T dlen, const char *src, int flag,
8941 const char *extra) {
8942 void *ctx;
8943 COMMON_INTERCEPTOR_ENTER(ctx, strsnvis, dst, dlen, src, flag, extra);
8944 if (src)
8945 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
8946 if (extra)
8947 COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
8948 int len = REAL(strsnvis)(dst, dlen, src, flag, extra);
8949 // The interface will be valid even if there is no space for NULL char
8950 if (dst && len >= 0)
8951 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1);
8952 return len;
8953}
8954INTERCEPTOR(int, strsvisx, char *dst, const char *src, SIZE_T len, int flag,
8955 const char *extra) {
8956 void *ctx;
8957 COMMON_INTERCEPTOR_ENTER(ctx, strsvisx, dst, src, len, flag, extra);
8958 if (src)
8959 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
8960 if (extra)
8961 COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
8962 int ret = REAL(strsvisx)(dst, src, len, flag, extra);
8963 if (dst)
8964 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
8965 return ret;
8966}
8967INTERCEPTOR(int, strsnvisx, char *dst, SIZE_T dlen, const char *src, SIZE_T len,
8968 int flag, const char *extra) {
8969 void *ctx;
8970 COMMON_INTERCEPTOR_ENTER(ctx, strsnvisx, dst, dlen, src, len, flag, extra);
8971 if (src)
8972 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
8973 if (extra)
8974 COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
8975 int ret = REAL(strsnvisx)(dst, dlen, src, len, flag, extra);
8976 if (dst && ret >= 0)
8977 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
8978 return ret;
8979}
8980INTERCEPTOR(int, strsenvisx, char *dst, SIZE_T dlen, const char *src,
8981 SIZE_T len, int flag, const char *extra, int *cerr_ptr) {
8982 void *ctx;
8983 COMMON_INTERCEPTOR_ENTER(ctx, strsenvisx, dst, dlen, src, len, flag, extra,
8984 cerr_ptr);
8985 if (src)
8986 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
8987 if (extra)
8988 COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, REAL(strlen)(extra) + 1);
8989 // FIXME: only need to be checked when "flag | VIS_NOLOCALE" doesn't hold
8990 // according to the implementation
8991 if (cerr_ptr)
8992 COMMON_INTERCEPTOR_READ_RANGE(ctx, cerr_ptr, sizeof(int));
8993 int ret = REAL(strsenvisx)(dst, dlen, src, len, flag, extra, cerr_ptr);
8994 if (dst && ret >= 0)
8995 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
8996 if (cerr_ptr)
8997 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cerr_ptr, sizeof(int));
8998 return ret;
8999}
9000INTERCEPTOR(int, unvis, char *cp, int c, int *astate, int flag) {
9001 void *ctx;
9002 COMMON_INTERCEPTOR_ENTER(ctx, unvis, cp, c, astate, flag);
9003 if (astate)
9004 COMMON_INTERCEPTOR_READ_RANGE(ctx, astate, sizeof(*astate));
9005 int ret = REAL(unvis)(cp, c, astate, flag);
9006 if (ret == unvis_valid || ret == unvis_validpush) {
9007 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cp, sizeof(*cp));
9008 }
9009 return ret;
9010}
9011INTERCEPTOR(int, strunvis, char *dst, const char *src) {
9012 void *ctx;
9013 COMMON_INTERCEPTOR_ENTER(ctx, strunvis, dst, src);
9014 if (src)
9015 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
9016 int ret = REAL(strunvis)(dst, src);
9017 if (ret != -1)
9018 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
9019 return ret;
9020}
9021INTERCEPTOR(int, strnunvis, char *dst, SIZE_T dlen, const char *src) {
9022 void *ctx;
9023 COMMON_INTERCEPTOR_ENTER(ctx, strnunvis, dst, dlen, src);
9024 if (src)
9025 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
9026 int ret = REAL(strnunvis)(dst, dlen, src);
9027 if (ret != -1)
9028 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
9029 return ret;
9030}
9031INTERCEPTOR(int, strunvisx, char *dst, const char *src, int flag) {
9032 void *ctx;
9033 COMMON_INTERCEPTOR_ENTER(ctx, strunvisx, dst, src, flag);
9034 if (src)
9035 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
9036 int ret = REAL(strunvisx)(dst, src, flag);
9037 if (ret != -1)
9038 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
9039 return ret;
9040}
9041INTERCEPTOR(int, strnunvisx, char *dst, SIZE_T dlen, const char *src,
9042 int flag) {
9043 void *ctx;
9044 COMMON_INTERCEPTOR_ENTER(ctx, strnunvisx, dst, dlen, src, flag);
9045 if (src)
9046 COMMON_INTERCEPTOR_READ_RANGE(ctx, src, REAL(strlen)(src) + 1);
9047 int ret = REAL(strnunvisx)(dst, dlen, src, flag);
9048 if (ret != -1)
9049 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
9050 return ret;
9051}
9052#define INIT_VIS \
9053 COMMON_INTERCEPT_FUNCTION(vis); \
9054 COMMON_INTERCEPT_FUNCTION(nvis); \
9055 COMMON_INTERCEPT_FUNCTION(strvis); \
9056 COMMON_INTERCEPT_FUNCTION(stravis); \
9057 COMMON_INTERCEPT_FUNCTION(strnvis); \
9058 COMMON_INTERCEPT_FUNCTION(strvisx); \
9059 COMMON_INTERCEPT_FUNCTION(strnvisx); \
9060 COMMON_INTERCEPT_FUNCTION(strenvisx); \
9061 COMMON_INTERCEPT_FUNCTION(svis); \
9062 COMMON_INTERCEPT_FUNCTION(snvis); \
9063 COMMON_INTERCEPT_FUNCTION(strsvis); \
9064 COMMON_INTERCEPT_FUNCTION(strsnvis); \
9065 COMMON_INTERCEPT_FUNCTION(strsvisx); \
9066 COMMON_INTERCEPT_FUNCTION(strsnvisx); \
9067 COMMON_INTERCEPT_FUNCTION(strsenvisx); \
9068 COMMON_INTERCEPT_FUNCTION(unvis); \
9069 COMMON_INTERCEPT_FUNCTION(strunvis); \
9070 COMMON_INTERCEPT_FUNCTION(strnunvis); \
9071 COMMON_INTERCEPT_FUNCTION(strunvisx); \
9072 COMMON_INTERCEPT_FUNCTION(strnunvisx)
9073#else
9074#define INIT_VIS
9075#endif
9076
9077#if SANITIZER_INTERCEPT_CDB
9078INTERCEPTOR(struct __sanitizer_cdbr *, cdbr_open, const char *path, int flags) {
9079 void *ctx;
9080 COMMON_INTERCEPTOR_ENTER(ctx, cdbr_open, path, flags);
9081 if (path)
9082 COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
9083 struct __sanitizer_cdbr *cdbr = REAL(cdbr_open)(path, flags);
9084 if (cdbr)
9085 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbr, sizeof(*cdbr));
9086 return cdbr;
9087}
9088
9089INTERCEPTOR(struct __sanitizer_cdbr *, cdbr_open_mem, void *base, SIZE_T size,
9090 int flags, void (*unmap)(void *, void *, SIZE_T), void *cookie) {
9091 void *ctx;
9092 COMMON_INTERCEPTOR_ENTER(ctx, cdbr_open_mem, base, size, flags, unmap,
9093 cookie);
9094 if (base && size)
9095 COMMON_INTERCEPTOR_READ_RANGE(ctx, base, size);
9096 struct __sanitizer_cdbr *cdbr =
9097 REAL(cdbr_open_mem)(base, size, flags, unmap, cookie);
9098 if (cdbr)
9099 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbr, sizeof(*cdbr));
9100 return cdbr;
9101}
9102
9103INTERCEPTOR(u32, cdbr_entries, struct __sanitizer_cdbr *cdbr) {
9104 void *ctx;
9105 COMMON_INTERCEPTOR_ENTER(ctx, cdbr_entries, cdbr);
9106 if (cdbr)
9107 COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbr, sizeof(*cdbr));
9108 return REAL(cdbr_entries)(cdbr);
9109}
9110
9111INTERCEPTOR(int, cdbr_get, struct __sanitizer_cdbr *cdbr, u32 index,
9112 const void **data, SIZE_T *datalen) {
9113 void *ctx;
9114 COMMON_INTERCEPTOR_ENTER(ctx, cdbr_get, cdbr, index, data, datalen);
9115 if (cdbr)
9116 COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbr, sizeof(*cdbr));
9117 int ret = REAL(cdbr_get)(cdbr, index, data, datalen);
9118 if (!ret) {
9119 if (data)
9120 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, sizeof(*data));
9121 if (datalen)
9122 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, datalen, sizeof(*datalen));
9123 if (data && datalen)
9124 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *data, *datalen);
9125 }
9126 return ret;
9127}
9128
9129INTERCEPTOR(int, cdbr_find, struct __sanitizer_cdbr *cdbr, const void *key,
9130 SIZE_T keylen, const void **data, SIZE_T *datalen) {
9131 void *ctx;
9132 COMMON_INTERCEPTOR_ENTER(ctx, cdbr_find, cdbr, key, keylen, data, datalen);
9133 if (cdbr)
9134 COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbr, sizeof(*cdbr));
9135 if (key)
9136 COMMON_INTERCEPTOR_READ_RANGE(ctx, key, keylen);
9137 int ret = REAL(cdbr_find)(cdbr, key, keylen, data, datalen);
9138 if (!ret) {
9139 if (data)
9140 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, sizeof(*data));
9141 if (datalen)
9142 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, datalen, sizeof(*datalen));
9143 if (data && datalen)
9144 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *data, *datalen);
9145 }
9146 return ret;
9147}
9148
9149INTERCEPTOR(void, cdbr_close, struct __sanitizer_cdbr *cdbr) {
9150 void *ctx;
9151 COMMON_INTERCEPTOR_ENTER(ctx, cdbr_close, cdbr);
9152 if (cdbr)
9153 COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbr, sizeof(*cdbr));
9154 REAL(cdbr_close)(cdbr);
9155}
9156
9157INTERCEPTOR(struct __sanitizer_cdbw *, cdbw_open) {
9158 void *ctx;
9159 COMMON_INTERCEPTOR_ENTER(ctx, cdbw_open);
9160 struct __sanitizer_cdbw *ret = REAL(cdbw_open)();
9161 if (ret)
9162 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, sizeof(*ret));
9163 return ret;
9164}
9165
9166INTERCEPTOR(int, cdbw_put, struct __sanitizer_cdbw *cdbw, const void *key,
9167 SIZE_T keylen, const void *data, SIZE_T datalen) {
9168 void *ctx;
9169 COMMON_INTERCEPTOR_ENTER(ctx, cdbw_put, cdbw, key, keylen, data, datalen);
9170 if (cdbw)
9171 COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
9172 if (data && datalen)
9173 COMMON_INTERCEPTOR_READ_RANGE(ctx, data, datalen);
9174 if (key && keylen)
9175 COMMON_INTERCEPTOR_READ_RANGE(ctx, key, keylen);
9176 int ret = REAL(cdbw_put)(cdbw, key, keylen, data, datalen);
9177 if (!ret && cdbw)
9178 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbw, sizeof(*cdbw));
9179 return ret;
9180}
9181
9182INTERCEPTOR(int, cdbw_put_data, struct __sanitizer_cdbw *cdbw, const void *data,
9183 SIZE_T datalen, u32 *index) {
9184 void *ctx;
9185 COMMON_INTERCEPTOR_ENTER(ctx, cdbw_put_data, cdbw, data, datalen, index);
9186 if (cdbw)
9187 COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
9188 if (data && datalen)
9189 COMMON_INTERCEPTOR_READ_RANGE(ctx, data, datalen);
9190 int ret = REAL(cdbw_put_data)(cdbw, data, datalen, index);
9191 if (!ret) {
9192 if (index)
9193 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, index, sizeof(*index));
9194 if (cdbw)
9195 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbw, sizeof(*cdbw));
9196 }
9197 return ret;
9198}
9199
9200INTERCEPTOR(int, cdbw_put_key, struct __sanitizer_cdbw *cdbw, const void *key,
9201 SIZE_T keylen, u32 index) {
9202 void *ctx;
9203 COMMON_INTERCEPTOR_ENTER(ctx, cdbw_put_key, cdbw, key, keylen, index);
9204 if (cdbw)
9205 COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
9206 if (key && keylen)
9207 COMMON_INTERCEPTOR_READ_RANGE(ctx, key, keylen);
9208 int ret = REAL(cdbw_put_key)(cdbw, key, keylen, index);
9209 if (!ret && cdbw)
9210 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbw, sizeof(*cdbw));
9211 return ret;
9212}
9213
9214INTERCEPTOR(int, cdbw_output, struct __sanitizer_cdbw *cdbw, int output,
9215 const char descr[16], u32 (*seedgen)(void)) {
9216 void *ctx;
9217 COMMON_INTERCEPTOR_ENTER(ctx, cdbw_output, cdbw, output, descr, seedgen);
9218 COMMON_INTERCEPTOR_FD_ACCESS(ctx, output);
9219 if (cdbw)
9220 COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
9221 if (descr)
9222 COMMON_INTERCEPTOR_READ_RANGE(ctx, descr, internal_strnlen(descr, 16));
9223 if (seedgen)
9224 COMMON_INTERCEPTOR_READ_RANGE(ctx, (void *)seedgen, sizeof(seedgen));
9225 int ret = REAL(cdbw_output)(cdbw, output, descr, seedgen);
9226 if (!ret) {
9227 if (cdbw)
9228 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbw, sizeof(*cdbw));
9229 if (output >= 0)
9230 COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, output);
9231 }
9232 return ret;
9233}
9234
9235INTERCEPTOR(void, cdbw_close, struct __sanitizer_cdbw *cdbw) {
9236 void *ctx;
9237 COMMON_INTERCEPTOR_ENTER(ctx, cdbw_close, cdbw);
9238 if (cdbw)
9239 COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
9240 REAL(cdbw_close)(cdbw);
9241}
9242
9243#define INIT_CDB \
9244 COMMON_INTERCEPT_FUNCTION(cdbr_open); \
9245 COMMON_INTERCEPT_FUNCTION(cdbr_open_mem); \
9246 COMMON_INTERCEPT_FUNCTION(cdbr_entries); \
9247 COMMON_INTERCEPT_FUNCTION(cdbr_get); \
9248 COMMON_INTERCEPT_FUNCTION(cdbr_find); \
9249 COMMON_INTERCEPT_FUNCTION(cdbr_close); \
9250 COMMON_INTERCEPT_FUNCTION(cdbw_open); \
9251 COMMON_INTERCEPT_FUNCTION(cdbw_put); \
9252 COMMON_INTERCEPT_FUNCTION(cdbw_put_data); \
9253 COMMON_INTERCEPT_FUNCTION(cdbw_put_key); \
9254 COMMON_INTERCEPT_FUNCTION(cdbw_output); \
9255 COMMON_INTERCEPT_FUNCTION(cdbw_close)
9256#else
9257#define INIT_CDB
9258#endif
9259
9260#if SANITIZER_INTERCEPT_GETFSENT
9261INTERCEPTOR(void *, getfsent) {
9262 void *ctx;
9263 COMMON_INTERCEPTOR_ENTER(ctx, getfsent);
9264 void *ret = REAL(getfsent)();
9265 if (ret)
9266 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, struct_fstab_sz);
9267 return ret;
9268}
9269
9270INTERCEPTOR(void *, getfsspec, const char *spec) {
9271 void *ctx;
9272 COMMON_INTERCEPTOR_ENTER(ctx, getfsspec, spec);
9273 if (spec)
9274 COMMON_INTERCEPTOR_READ_RANGE(ctx, spec, REAL(strlen)(spec) + 1);
9275 void *ret = REAL(getfsspec)(spec);
9276 if (ret)
9277 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, struct_fstab_sz);
9278 return ret;
9279}
9280
9281INTERCEPTOR(void *, getfsfile, const char *file) {
9282 void *ctx;
9283 COMMON_INTERCEPTOR_ENTER(ctx, getfsfile, file);
9284 if (file)
9285 COMMON_INTERCEPTOR_READ_RANGE(ctx, file, REAL(strlen)(file) + 1);
9286 void *ret = REAL(getfsfile)(file);
9287 if (ret)
9288 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, struct_fstab_sz);
9289 return ret;
9290}
9291
9292#define INIT_GETFSENT \
9293 COMMON_INTERCEPT_FUNCTION(getfsent); \
9294 COMMON_INTERCEPT_FUNCTION(getfsspec); \
9295 COMMON_INTERCEPT_FUNCTION(getfsfile);
9296#else
9297#define INIT_GETFSENT
9298#endif
9299
9300#if SANITIZER_INTERCEPT_ARC4RANDOM
9301INTERCEPTOR(void, arc4random_buf, void *buf, SIZE_T len) {
9302 void *ctx;
9303 COMMON_INTERCEPTOR_ENTER(ctx, arc4random_buf, buf, len);
9304 REAL(arc4random_buf)(buf, len);
9305 if (buf && len)
9306 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, len);
9307}
9308
9309INTERCEPTOR(void, arc4random_addrandom, u8 *dat, int datlen) {
9310 void *ctx;
9311 COMMON_INTERCEPTOR_ENTER(ctx, arc4random_addrandom, dat, datlen);
9312 if (dat && datlen)
9313 COMMON_INTERCEPTOR_READ_RANGE(ctx, dat, datlen);
9314 REAL(arc4random_addrandom)(dat, datlen);
9315}
9316
9317#define INIT_ARC4RANDOM \
9318 COMMON_INTERCEPT_FUNCTION(arc4random_buf); \
9319 COMMON_INTERCEPT_FUNCTION(arc4random_addrandom);
9320#else
9321#define INIT_ARC4RANDOM
9322#endif
9323
9324#if SANITIZER_INTERCEPT_POPEN
9325INTERCEPTOR(__sanitizer_FILE *, popen, const char *command, const char *type) {
9326 void *ctx;
9327 COMMON_INTERCEPTOR_ENTER(ctx, popen, command, type);
9328 if (command)
9329 COMMON_INTERCEPTOR_READ_RANGE(ctx, command, REAL(strlen)(command) + 1);
9330 if (type)
9331 COMMON_INTERCEPTOR_READ_RANGE(ctx, type, REAL(strlen)(type) + 1);
9332 __sanitizer_FILE *res = REAL(popen)(command, type);
9333 COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, nullptr);
9334 if (res) unpoison_file(res);
9335 return res;
9336}
9337#define INIT_POPEN COMMON_INTERCEPT_FUNCTION(popen)
9338#else
9339#define INIT_POPEN
9340#endif
9341
9342#if SANITIZER_INTERCEPT_POPENVE
9343INTERCEPTOR(__sanitizer_FILE *, popenve, const char *path,
9344 char *const *argv, char *const *envp, const char *type) {
9345 void *ctx;
9346 COMMON_INTERCEPTOR_ENTER(ctx, popenve, path, argv, envp, type);
9347 if (path)
9348 COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
9349 if (argv) {
9350 for (char *const *pa = argv; ; ++pa) {
9351 COMMON_INTERCEPTOR_READ_RANGE(ctx, pa, sizeof(char **));
9352 if (!*pa)
9353 break;
9354 COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, REAL(strlen)(*pa) + 1);
9355 }
9356 }
9357 if (envp) {
9358 for (char *const *pa = envp; ; ++pa) {
9359 COMMON_INTERCEPTOR_READ_RANGE(ctx, pa, sizeof(char **));
9360 if (!*pa)
9361 break;
9362 COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, REAL(strlen)(*pa) + 1);
9363 }
9364 }
9365 if (type)
9366 COMMON_INTERCEPTOR_READ_RANGE(ctx, type, REAL(strlen)(type) + 1);
9367 __sanitizer_FILE *res = REAL(popenve)(path, argv, envp, type);
9368 COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, nullptr);
9369 if (res) unpoison_file(res);
9370 return res;
9371}
9372#define INIT_POPENVE COMMON_INTERCEPT_FUNCTION(popenve)
9373#else
9374#define INIT_POPENVE
9375#endif
9376
9377#if SANITIZER_INTERCEPT_PCLOSE
9378INTERCEPTOR(int, pclose, __sanitizer_FILE *fp) {
9379 void *ctx;
9380 COMMON_INTERCEPTOR_ENTER(ctx, pclose, fp);
9381 COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
9382 const FileMetadata *m = GetInterceptorMetadata(fp);
9383 int res = REAL(pclose)(fp);
9384 if (m) {
9385 COMMON_INTERCEPTOR_INITIALIZE_RANGE(*m->addr, *m->size);
9386 DeleteInterceptorMetadata(fp);
9387 }
9388 return res;
9389}
9390#define INIT_PCLOSE COMMON_INTERCEPT_FUNCTION(pclose);
9391#else
9392#define INIT_PCLOSE
9393#endif
9394
9395#if SANITIZER_INTERCEPT_FUNOPEN
9396typedef int (*funopen_readfn)(void *cookie, char *buf, int len);
9397typedef int (*funopen_writefn)(void *cookie, const char *buf, int len);
9398typedef OFF_T (*funopen_seekfn)(void *cookie, OFF_T offset, int whence);
9399typedef int (*funopen_closefn)(void *cookie);
9400
9401struct WrappedFunopenCookie {
9402 void *real_cookie;
9403 funopen_readfn real_read;
9404 funopen_writefn real_write;
9405 funopen_seekfn real_seek;
9406 funopen_closefn real_close;
9407};
9408
9409static int wrapped_funopen_read(void *cookie, char *buf, int len) {
9410 COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
9411 WrappedFunopenCookie *wrapped_cookie = (WrappedFunopenCookie *)cookie;
9412 funopen_readfn real_read = wrapped_cookie->real_read;
9413 return real_read(wrapped_cookie->real_cookie, buf, len);
9414}
9415
9416static int wrapped_funopen_write(void *cookie, const char *buf, int len) {
9417 COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
9418 WrappedFunopenCookie *wrapped_cookie = (WrappedFunopenCookie *)cookie;
9419 funopen_writefn real_write = wrapped_cookie->real_write;
9420 return real_write(wrapped_cookie->real_cookie, buf, len);
9421}
9422
9423static OFF_T wrapped_funopen_seek(void *cookie, OFF_T offset, int whence) {
9424 COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
9425 WrappedFunopenCookie *wrapped_cookie = (WrappedFunopenCookie *)cookie;
9426 funopen_seekfn real_seek = wrapped_cookie->real_seek;
9427 return real_seek(wrapped_cookie->real_cookie, offset, whence);
9428}
9429
9430static int wrapped_funopen_close(void *cookie) {
9431 COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
9432 WrappedFunopenCookie *wrapped_cookie = (WrappedFunopenCookie *)cookie;
9433 funopen_closefn real_close = wrapped_cookie->real_close;
9434 int res = real_close(wrapped_cookie->real_cookie);
9435 InternalFree(wrapped_cookie);
9436 return res;
9437}
9438
9439INTERCEPTOR(__sanitizer_FILE *, funopen, void *cookie, funopen_readfn readfn,
9440 funopen_writefn writefn, funopen_seekfn seekfn,
9441 funopen_closefn closefn) {
9442 void *ctx;
9443 COMMON_INTERCEPTOR_ENTER(ctx, funopen, cookie, readfn, writefn, seekfn,
9444 closefn);
9445
9446 WrappedFunopenCookie *wrapped_cookie =
9447 (WrappedFunopenCookie *)InternalAlloc(sizeof(WrappedFunopenCookie));
9448 wrapped_cookie->real_cookie = cookie;
9449 wrapped_cookie->real_read = readfn;
9450 wrapped_cookie->real_write = writefn;
9451 wrapped_cookie->real_seek = seekfn;
9452 wrapped_cookie->real_close = closefn;
9453
9454 __sanitizer_FILE *res =
9455 REAL(funopen)(wrapped_cookie,
9456 readfn ? wrapped_funopen_read : nullptr,
9457 writefn ? wrapped_funopen_write : nullptr,
9458 seekfn ? wrapped_funopen_seek : nullptr,
9459 closefn ? wrapped_funopen_close : nullptr);
9460 if (res)
9461 unpoison_file(res);
9462 return res;
9463}
9464#define INIT_FUNOPEN COMMON_INTERCEPT_FUNCTION(funopen)
9465#else
9466#define INIT_FUNOPEN
9467#endif
9468
9469#if SANITIZER_INTERCEPT_FUNOPEN2
9470typedef SSIZE_T (*funopen2_readfn)(void *cookie, void *buf, SIZE_T len);
9471typedef SSIZE_T (*funopen2_writefn)(void *cookie, const void *buf, SIZE_T len);
9472typedef OFF_T (*funopen2_seekfn)(void *cookie, OFF_T offset, int whence);
9473typedef int (*funopen2_flushfn)(void *cookie);
9474typedef int (*funopen2_closefn)(void *cookie);
9475
9476struct WrappedFunopen2Cookie {
9477 void *real_cookie;
9478 funopen2_readfn real_read;
9479 funopen2_writefn real_write;
9480 funopen2_seekfn real_seek;
9481 funopen2_flushfn real_flush;
9482 funopen2_closefn real_close;
9483};
9484
9485static SSIZE_T wrapped_funopen2_read(void *cookie, void *buf, SIZE_T len) {
9486 COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
9487 WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie;
9488 funopen2_readfn real_read = wrapped_cookie->real_read;
9489 return real_read(wrapped_cookie->real_cookie, buf, len);
9490}
9491
9492static SSIZE_T wrapped_funopen2_write(void *cookie, const void *buf,
9493 SIZE_T len) {
9494 COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
9495 WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie;
9496 funopen2_writefn real_write = wrapped_cookie->real_write;
9497 return real_write(wrapped_cookie->real_cookie, buf, len);
9498}
9499
9500static OFF_T wrapped_funopen2_seek(void *cookie, OFF_T offset, int whence) {
9501 COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
9502 WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie;
9503 funopen2_seekfn real_seek = wrapped_cookie->real_seek;
9504 return real_seek(wrapped_cookie->real_cookie, offset, whence);
9505}
9506
9507static int wrapped_funopen2_flush(void *cookie) {
9508 COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
9509 WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie;
9510 funopen2_flushfn real_flush = wrapped_cookie->real_flush;
9511 return real_flush(wrapped_cookie->real_cookie);
9512}
9513
9514static int wrapped_funopen2_close(void *cookie) {
9515 COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
9516 WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie;
9517 funopen2_closefn real_close = wrapped_cookie->real_close;
9518 int res = real_close(wrapped_cookie->real_cookie);
9519 InternalFree(wrapped_cookie);
9520 return res;
9521}
9522
9523INTERCEPTOR(__sanitizer_FILE *, funopen2, void *cookie, funopen2_readfn readfn,
9524 funopen2_writefn writefn, funopen2_seekfn seekfn,
9525 funopen2_flushfn flushfn, funopen2_closefn closefn) {
9526 void *ctx;
9527 COMMON_INTERCEPTOR_ENTER(ctx, funopen2, cookie, readfn, writefn, seekfn,
9528 flushfn, closefn);
9529
9530 WrappedFunopen2Cookie *wrapped_cookie =
9531 (WrappedFunopen2Cookie *)InternalAlloc(sizeof(WrappedFunopen2Cookie));
9532 wrapped_cookie->real_cookie = cookie;
9533 wrapped_cookie->real_read = readfn;
9534 wrapped_cookie->real_write = writefn;
9535 wrapped_cookie->real_seek = seekfn;
9536 wrapped_cookie->real_flush = flushfn;
9537 wrapped_cookie->real_close = closefn;
9538
9539 __sanitizer_FILE *res =
9540 REAL(funopen2)(wrapped_cookie,
9541 readfn ? wrapped_funopen2_read : nullptr,
9542 writefn ? wrapped_funopen2_write : nullptr,
9543 seekfn ? wrapped_funopen2_seek : nullptr,
9544 flushfn ? wrapped_funopen2_flush : nullptr,
9545 closefn ? wrapped_funopen2_close : nullptr);
9546 if (res)
9547 unpoison_file(res);
9548 return res;
9549}
9550#define INIT_FUNOPEN2 COMMON_INTERCEPT_FUNCTION(funopen2)
9551#else
9552#define INIT_FUNOPEN2
9553#endif
9554
9555#if SANITIZER_INTERCEPT_FDEVNAME
9556INTERCEPTOR(char *, fdevname, int fd) {
9557 void *ctx;
9558 COMMON_INTERCEPTOR_ENTER(ctx, fdevname, fd);
9559 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
9560 char *name = REAL(fdevname)(fd);
9561 if (name) {
9562 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, REAL(strlen)(name) + 1);
9563 if (fd > 0)
9564 COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
9565 }
9566 return name;
9567}
9568
9569INTERCEPTOR(char *, fdevname_r, int fd, char *buf, SIZE_T len) {
9570 void *ctx;
9571 COMMON_INTERCEPTOR_ENTER(ctx, fdevname_r, fd, buf, len);
9572 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
9573 char *name = REAL(fdevname_r)(fd, buf, len);
9574 if (name && buf && len > 0) {
9575 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
9576 if (fd > 0)
9577 COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
9578 }
9579 return name;
9580}
9581
9582#define INIT_FDEVNAME \
9583 COMMON_INTERCEPT_FUNCTION(fdevname); \
9584 COMMON_INTERCEPT_FUNCTION(fdevname_r);
9585#else
9586#define INIT_FDEVNAME
9587#endif
9588
9589#if SANITIZER_INTERCEPT_GETUSERSHELL
9590INTERCEPTOR(char *, getusershell) {
9591 void *ctx;
9592 COMMON_INTERCEPTOR_ENTER(ctx, getusershell);
9593 char *res = REAL(getusershell)();
9594 if (res)
9595 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
9596 return res;
9597}
9598
9599#define INIT_GETUSERSHELL COMMON_INTERCEPT_FUNCTION(getusershell);
9600#else
9601#define INIT_GETUSERSHELL
9602#endif
9603
9604#if SANITIZER_INTERCEPT_SL_INIT
9605INTERCEPTOR(void *, sl_init) {
9606 void *ctx;
9607 COMMON_INTERCEPTOR_ENTER(ctx, sl_init);
9608 void *res = REAL(sl_init)();
9609 if (res)
9610 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, __sanitizer::struct_StringList_sz);
9611 return res;
9612}
9613
9614INTERCEPTOR(int, sl_add, void *sl, char *item) {
9615 void *ctx;
9616 COMMON_INTERCEPTOR_ENTER(ctx, sl_add, sl, item);
9617 if (sl)
9618 COMMON_INTERCEPTOR_READ_RANGE(ctx, sl, __sanitizer::struct_StringList_sz);
9619 if (item)
9620 COMMON_INTERCEPTOR_READ_RANGE(ctx, item, REAL(strlen)(item) + 1);
9621 int res = REAL(sl_add)(sl, item);
9622 if (!res)
9623 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sl, __sanitizer::struct_StringList_sz);
9624 return res;
9625}
9626
9627INTERCEPTOR(char *, sl_find, void *sl, const char *item) {
9628 void *ctx;
9629 COMMON_INTERCEPTOR_ENTER(ctx, sl_find, sl, item);
9630 if (sl)
9631 COMMON_INTERCEPTOR_READ_RANGE(ctx, sl, __sanitizer::struct_StringList_sz);
9632 if (item)
9633 COMMON_INTERCEPTOR_READ_RANGE(ctx, item, REAL(strlen)(item) + 1);
9634 char *res = REAL(sl_find)(sl, item);
9635 if (res)
9636 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
9637 return res;
9638}
9639
9640INTERCEPTOR(void, sl_free, void *sl, int freeall) {
9641 void *ctx;
9642 COMMON_INTERCEPTOR_ENTER(ctx, sl_free, sl, freeall);
9643 if (sl)
9644 COMMON_INTERCEPTOR_READ_RANGE(ctx, sl, __sanitizer::struct_StringList_sz);
9645 REAL(sl_free)(sl, freeall);
9646}
9647
9648#define INIT_SL_INIT \
9649 COMMON_INTERCEPT_FUNCTION(sl_init); \
9650 COMMON_INTERCEPT_FUNCTION(sl_add); \
9651 COMMON_INTERCEPT_FUNCTION(sl_find); \
9652 COMMON_INTERCEPT_FUNCTION(sl_free);
9653#else
9654#define INIT_SL_INIT
9655#endif
9656
9657#if SANITIZER_INTERCEPT_GETRANDOM
9658INTERCEPTOR(SSIZE_T, getrandom, void *buf, SIZE_T buflen, unsigned int flags) {
9659 void *ctx;
9660 COMMON_INTERCEPTOR_ENTER(ctx, getrandom, buf, buflen, flags);
9661 SSIZE_T n = REAL(getrandom)(buf, buflen, flags);
9662 if (n > 0) {
9663 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, n);
9664 }
9665 return n;
9666}
9667#define INIT_GETRANDOM COMMON_INTERCEPT_FUNCTION(getrandom)
9668#else
9669#define INIT_GETRANDOM
9670#endif
9671
9672#if SANITIZER_INTERCEPT_CRYPT
9673INTERCEPTOR(char *, crypt, char *key, char *salt) {
9674 void *ctx;
9675 COMMON_INTERCEPTOR_ENTER(ctx, crypt, key, salt);
9676 COMMON_INTERCEPTOR_READ_RANGE(ctx, key, internal_strlen(key) + 1);
9677 COMMON_INTERCEPTOR_READ_RANGE(ctx, salt, internal_strlen(salt) + 1);
9678 char *res = REAL(crypt)(key, salt);
9679 if (res != nullptr)
9680 COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
9681 return res;
9682}
9683#define INIT_CRYPT COMMON_INTERCEPT_FUNCTION(crypt);
9684#else
9685#define INIT_CRYPT
9686#endif
9687
9688#if SANITIZER_INTERCEPT_CRYPT_R
9689INTERCEPTOR(char *, crypt_r, char *key, char *salt, void *data) {
9690 void *ctx;
9691 COMMON_INTERCEPTOR_ENTER(ctx, crypt_r, key, salt, data);
9692 COMMON_INTERCEPTOR_READ_RANGE(ctx, key, internal_strlen(key) + 1);
9693 COMMON_INTERCEPTOR_READ_RANGE(ctx, salt, internal_strlen(salt) + 1);
9694 char *res = REAL(crypt_r)(key, salt, data);
9695 if (res != nullptr) {
9696 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data,
9697 __sanitizer::struct_crypt_data_sz);
9698 COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
9699 }
9700 return res;
9701}
9702#define INIT_CRYPT_R COMMON_INTERCEPT_FUNCTION(crypt_r);
9703#else
9704#define INIT_CRYPT_R
9705#endif
9706
9707#if SANITIZER_INTERCEPT_GETENTROPY
9708INTERCEPTOR(int, getentropy, void *buf, SIZE_T buflen) {
9709 void *ctx;
9710 COMMON_INTERCEPTOR_ENTER(ctx, getentropy, buf, buflen);
9711 int r = REAL(getentropy)(buf, buflen);
9712 if (r == 0) {
9713 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
9714 }
9715 return r;
9716}
9717#define INIT_GETENTROPY COMMON_INTERCEPT_FUNCTION(getentropy)
9718#else
9719#define INIT_GETENTROPY
9720#endif
9721
9722#if SANITIZER_INTERCEPT_QSORT
9723// Glibc qsort uses a temporary buffer allocated either on stack or on heap.
9724// Poisoned memory from there may get copied into the comparator arguments,
9725// where it needs to be dealt with. But even that is not enough - the results of
9726// the sort may be copied into the input/output array based on the results of
9727// the comparator calls, but directly from the temp memory, bypassing the
9728// unpoisoning done in wrapped_qsort_compar. We deal with this by, again,
9729// unpoisoning the entire array after the sort is done.
9730//
9731// We can not check that the entire array is initialized at the beginning. IMHO,
9732// it's fine for parts of the sorted objects to contain uninitialized memory,
9733// ex. as padding in structs.
9734typedef int (*qsort_compar_f)(const void *, const void *);
9735static THREADLOCAL qsort_compar_f qsort_compar;
9736static THREADLOCAL SIZE_T qsort_size;
9737int wrapped_qsort_compar(const void *a, const void *b) {
9738 COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
9739 COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, qsort_size);
9740 COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, qsort_size);
9741 return qsort_compar(a, b);
9742}
9743
9744INTERCEPTOR(void, qsort, void *base, SIZE_T nmemb, SIZE_T size,
9745 qsort_compar_f compar) {
9746 void *ctx;
9747 COMMON_INTERCEPTOR_ENTER(ctx, qsort, base, nmemb, size, compar);
9748 // Run the comparator over all array elements to detect any memory issues.
9749 if (nmemb > 1) {
9750 for (SIZE_T i = 0; i < nmemb - 1; ++i) {
9751 void *p = (void *)((char *)base + i * size);
9752 void *q = (void *)((char *)base + (i + 1) * size);
9753 COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
9754 compar(p, q);
9755 }
9756 }
9757 qsort_compar_f old_compar = qsort_compar;
9758 qsort_compar = compar;
9759 SIZE_T old_size = qsort_size;
9760 qsort_size = size;
9761 REAL(qsort)(base, nmemb, size, wrapped_qsort_compar);
9762 qsort_compar = old_compar;
9763 qsort_size = old_size;
9764 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, base, nmemb * size);
9765}
9766#define INIT_QSORT COMMON_INTERCEPT_FUNCTION(qsort)
9767#else
9768#define INIT_QSORT
9769#endif
9770
9771#if SANITIZER_INTERCEPT_QSORT_R
9772typedef int (*qsort_r_compar_f)(const void *, const void *, void *);
9773static THREADLOCAL qsort_r_compar_f qsort_r_compar;
9774static THREADLOCAL SIZE_T qsort_r_size;
9775int wrapped_qsort_r_compar(const void *a, const void *b, void *arg) {
9776 COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
9777 COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, qsort_r_size);
9778 COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, qsort_r_size);
9779 return qsort_r_compar(a, b, arg);
9780}
9781
9782INTERCEPTOR(void, qsort_r, void *base, SIZE_T nmemb, SIZE_T size,
9783 qsort_r_compar_f compar, void *arg) {
9784 void *ctx;
9785 COMMON_INTERCEPTOR_ENTER(ctx, qsort_r, base, nmemb, size, compar, arg);
9786 // Run the comparator over all array elements to detect any memory issues.
9787 if (nmemb > 1) {
9788 for (SIZE_T i = 0; i < nmemb - 1; ++i) {
9789 void *p = (void *)((char *)base + i * size);
9790 void *q = (void *)((char *)base + (i + 1) * size);
9791 COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
9792 compar(p, q, arg);
9793 }
9794 }
9795 qsort_r_compar_f old_compar = qsort_r_compar;
9796 qsort_r_compar = compar;
9797 SIZE_T old_size = qsort_r_size;
9798 qsort_r_size = size;
9799 REAL(qsort_r)(base, nmemb, size, wrapped_qsort_r_compar, arg);
9800 qsort_r_compar = old_compar;
9801 qsort_r_size = old_size;
9802 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, base, nmemb * size);
9803}
9804#define INIT_QSORT_R COMMON_INTERCEPT_FUNCTION(qsort_r)
9805#else
9806#define INIT_QSORT_R
9807#endif
9808
9809#if SANITIZER_INTERCEPT_SIGALTSTACK
9810INTERCEPTOR(int, sigaltstack, void *ss, void *oss) {
9811 void *ctx;
9812 COMMON_INTERCEPTOR_ENTER(ctx, sigaltstack, ss, oss);
9813 int r = REAL(sigaltstack)(ss, oss);
9814 if (r == 0 && oss != nullptr) {
9815 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oss, struct_stack_t_sz);
9816 }
9817 return r;
9818}
9819#define INIT_SIGALTSTACK COMMON_INTERCEPT_FUNCTION(sigaltstack)
9820#else
9821#define INIT_SIGALTSTACK
9822#endif
9823
9824#if SANITIZER_INTERCEPT_UNAME
9825INTERCEPTOR(int, uname, struct utsname *utsname) {
9826#if SANITIZER_LINUX
9827 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
9828 return internal_uname(utsname);
9829#endif
9830 void *ctx;
9831 COMMON_INTERCEPTOR_ENTER(ctx, uname, utsname);
9832 int res = REAL(uname)(utsname);
9833 if (!res)
9834 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, utsname,
9835 __sanitizer::struct_utsname_sz);
9836 return res;
9837}
9838#define INIT_UNAME COMMON_INTERCEPT_FUNCTION(uname)
9839#else
9840#define INIT_UNAME
9841#endif
9842
9843#if SANITIZER_INTERCEPT___XUNAME
9844// FreeBSD's <sys/utsname.h> define uname() as
9845// static __inline int uname(struct utsname *name) {
9846// return __xuname(SYS_NMLN, (void*)name);
9847// }
9848INTERCEPTOR(int, __xuname, int size, void *utsname) {
9849 void *ctx;
9850 COMMON_INTERCEPTOR_ENTER(ctx, __xuname, size, utsname);
9851 int res = REAL(__xuname)(size, utsname);
9852 if (!res)
9853 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, utsname,
9854 __sanitizer::struct_utsname_sz);
9855 return res;
9856}
9857#define INIT___XUNAME COMMON_INTERCEPT_FUNCTION(__xuname)
9858#else
9859#define INIT___XUNAME
9860#endif
9861
9862#include "sanitizer_common_interceptors_netbsd_compat.inc"
9863
9864static void InitializeCommonInterceptors() {
9865#if SI_POSIX
9866 static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1];
9867 interceptor_metadata_map = new ((void *)&metadata_mem) MetadataHashMap();
9868#endif
9869
9870 INIT_MMAP;
9871 INIT_MMAP64;
9872 INIT_TEXTDOMAIN;
9873 INIT_STRLEN;
9874 INIT_STRNLEN;
9875 INIT_STRNDUP;
9876 INIT___STRNDUP;
9877 INIT_STRCMP;
9878 INIT_STRNCMP;
9879 INIT_STRCASECMP;
9880 INIT_STRNCASECMP;
9881 INIT_STRSTR;
9882 INIT_STRCASESTR;
9883 INIT_STRCHR;
9884 INIT_STRCHRNUL;
9885 INIT_STRRCHR;
9886 INIT_STRSPN;
9887 INIT_STRTOK;
9888 INIT_STRPBRK;
9889 INIT_STRXFRM;
9890 INIT___STRXFRM_L;
9891 INIT_MEMSET;
9892 INIT_MEMMOVE;
9893 INIT_MEMCPY;
9894 INIT_MEMCHR;
9895 INIT_MEMCMP;
9896 INIT_BCMP;
9897 INIT_MEMRCHR;
9898 INIT_MEMMEM;
9899 INIT_READ;
9900 INIT_FREAD;
9901 INIT_PREAD;
9902 INIT_PREAD64;
9903 INIT_READV;
9904 INIT_PREADV;
9905 INIT_PREADV64;
9906 INIT_WRITE;
9907 INIT_FWRITE;
9908 INIT_PWRITE;
9909 INIT_PWRITE64;
9910 INIT_WRITEV;
9911 INIT_PWRITEV;
9912 INIT_PWRITEV64;
9913 INIT_FGETS;
9914 INIT_FPUTS;
9915 INIT_PUTS;
9916 INIT_PRCTL;
9917 INIT_LOCALTIME_AND_FRIENDS;
9918 INIT_STRPTIME;
9919 INIT_SCANF;
9920 INIT_ISOC99_SCANF;
9921 INIT_PRINTF;
9922 INIT_PRINTF_L;
9923 INIT_ISOC99_PRINTF;
9924 INIT_FREXP;
9925 INIT_FREXPF_FREXPL;
9926 INIT_GETPWNAM_AND_FRIENDS;
9927 INIT_GETPWNAM_R_AND_FRIENDS;
9928 INIT_GETPWENT;
9929 INIT_FGETPWENT;
9930 INIT_GETPWENT_R;
9931 INIT_FGETPWENT_R;
9932 INIT_FGETGRENT_R;
9933 INIT_SETPWENT;
9934 INIT_CLOCK_GETTIME;
9935 INIT_CLOCK_GETCPUCLOCKID;
9936 INIT_GETITIMER;
9937 INIT_TIME;
9938 INIT_GLOB;
9939 INIT_GLOB64;
9940 INIT_WAIT;
9941 INIT_WAIT4;
9942 INIT_INET;
9943 INIT_PTHREAD_GETSCHEDPARAM;
9944 INIT_GETADDRINFO;
9945 INIT_GETNAMEINFO;
9946 INIT_GETSOCKNAME;
9947 INIT_GETHOSTBYNAME;
9948 INIT_GETHOSTBYNAME2;
9949 INIT_GETHOSTBYNAME_R;
9950 INIT_GETHOSTBYNAME2_R;
9951 INIT_GETHOSTBYADDR_R;
9952 INIT_GETHOSTENT_R;
9953 INIT_GETSOCKOPT;
9954 INIT_ACCEPT;
9955 INIT_ACCEPT4;
9956 INIT_PACCEPT;
9957 INIT_MODF;
9958 INIT_RECVMSG;
9959 INIT_SENDMSG;
9960 INIT_RECVMMSG;
9961 INIT_SENDMMSG;
9962 INIT_SYSMSG;
9963 INIT_GETPEERNAME;
9964 INIT_IOCTL;
9965 INIT_INET_ATON;
9966 INIT_SYSINFO;
9967 INIT_READDIR;
9968 INIT_READDIR64;
9969 INIT_PTRACE;
9970 INIT_SETLOCALE;
9971 INIT_GETCWD;
9972 INIT_GET_CURRENT_DIR_NAME;
9973 INIT_STRTOIMAX;
9974 INIT_MBSTOWCS;
9975 INIT_MBSNRTOWCS;
9976 INIT_WCSTOMBS;
9977 INIT_WCSNRTOMBS;
9978 INIT_WCRTOMB;
9979 INIT_WCTOMB;
9980 INIT_TCGETATTR;
9981 INIT_REALPATH;
9982 INIT_CANONICALIZE_FILE_NAME;
9983 INIT_CONFSTR;
9984 INIT_SCHED_GETAFFINITY;
9985 INIT_SCHED_GETPARAM;
9986 INIT_STRERROR;
9987 INIT_STRERROR_R;
9988 INIT_XPG_STRERROR_R;
9989 INIT_SCANDIR;
9990 INIT_SCANDIR64;
9991 INIT_GETGROUPS;
9992 INIT_POLL;
9993 INIT_PPOLL;
9994 INIT_WORDEXP;
9995 INIT_SIGWAIT;
9996 INIT_SIGWAITINFO;
9997 INIT_SIGTIMEDWAIT;
9998 INIT_SIGSETOPS;
9999 INIT_SIGPENDING;
10000 INIT_SIGPROCMASK;
10001 INIT_PTHREAD_SIGMASK;
10002 INIT_BACKTRACE;
10003 INIT__EXIT;
10004 INIT_PTHREAD_MUTEX_LOCK;
10005 INIT_PTHREAD_MUTEX_UNLOCK;
10006 INIT___PTHREAD_MUTEX_LOCK;
10007 INIT___PTHREAD_MUTEX_UNLOCK;
10008 INIT___LIBC_MUTEX_LOCK;
10009 INIT___LIBC_MUTEX_UNLOCK;
10010 INIT___LIBC_THR_SETCANCELSTATE;
10011 INIT_GETMNTENT;
10012 INIT_GETMNTENT_R;
10013 INIT_STATFS;
10014 INIT_STATFS64;
10015 INIT_STATVFS;
10016 INIT_STATVFS64;
10017 INIT_INITGROUPS;
10018 INIT_ETHER_NTOA_ATON;
10019 INIT_ETHER_HOST;
10020 INIT_ETHER_R;
10021 INIT_SHMCTL;
10022 INIT_RANDOM_R;
10023 INIT_PTHREAD_ATTR_GET;
10024 INIT_PTHREAD_ATTR_GET_SCHED;
10025 INIT_PTHREAD_ATTR_GETINHERITSCHED;
10026 INIT_PTHREAD_ATTR_GETAFFINITY_NP;
10027 INIT_PTHREAD_MUTEXATTR_GETPSHARED;
10028 INIT_PTHREAD_MUTEXATTR_GETTYPE;
10029 INIT_PTHREAD_MUTEXATTR_GETPROTOCOL;
10030 INIT_PTHREAD_MUTEXATTR_GETPRIOCEILING;
10031 INIT_PTHREAD_MUTEXATTR_GETROBUST;
10032 INIT_PTHREAD_MUTEXATTR_GETROBUST_NP;
10033 INIT_PTHREAD_RWLOCKATTR_GETPSHARED;
10034 INIT_PTHREAD_RWLOCKATTR_GETKIND_NP;
10035 INIT_PTHREAD_CONDATTR_GETPSHARED;
10036 INIT_PTHREAD_CONDATTR_GETCLOCK;
10037 INIT_PTHREAD_BARRIERATTR_GETPSHARED;
10038 INIT_TMPNAM;
10039 INIT_TMPNAM_R;
10040 INIT_TTYNAME;
10041 INIT_TTYNAME_R;
10042 INIT_TEMPNAM;
10043 INIT_PTHREAD_SETNAME_NP;
10044 INIT_PTHREAD_GETNAME_NP;
10045 INIT_SINCOS;
10046 INIT_REMQUO;
10047 INIT_REMQUOL;
10048 INIT_LGAMMA;
10049 INIT_LGAMMAL;
10050 INIT_LGAMMA_R;
10051 INIT_LGAMMAL_R;
10052 INIT_DRAND48_R;
10053 INIT_RAND_R;
10054 INIT_GETLINE;
10055 INIT_ICONV;
10056 INIT_TIMES;
10057 INIT_TLS_GET_ADDR;
10058 INIT_LISTXATTR;
10059 INIT_GETXATTR;
10060 INIT_GETRESID;
10061 INIT_GETIFADDRS;
10062 INIT_IF_INDEXTONAME;
10063 INIT_CAPGET;
10064 INIT_AEABI_MEM;
10065 INIT___BZERO;
10066 INIT_BZERO;
10067 INIT_FTIME;
10068 INIT_XDR;
10069 INIT_TSEARCH;
10070 INIT_LIBIO_INTERNALS;
10071 INIT_FOPEN;
10072 INIT_FOPEN64;
10073 INIT_OPEN_MEMSTREAM;
10074 INIT_OBSTACK;
10075 INIT_FFLUSH;
10076 INIT_FCLOSE;
10077 INIT_DLOPEN_DLCLOSE;
10078 INIT_GETPASS;
10079 INIT_TIMERFD;
10080 INIT_MLOCKX;
10081 INIT_FOPENCOOKIE;
10082 INIT_SEM;
10083 INIT_PTHREAD_SETCANCEL;
10084 INIT_MINCORE;
10085 INIT_PROCESS_VM_READV;
10086 INIT_CTERMID;
10087 INIT_CTERMID_R;
10088 INIT_RECV_RECVFROM;
10089 INIT_SEND_SENDTO;
10090 INIT_STAT;
10091 INIT_EVENTFD_READ_WRITE;
10092 INIT_LSTAT;
10093 INIT___XSTAT;
10094 INIT___XSTAT64;
10095 INIT___LXSTAT;
10096 INIT___LXSTAT64;
10097 // FIXME: add other *stat interceptors.
10098 INIT_UTMP;
10099 INIT_UTMPX;
10100 INIT_GETLOADAVG;
10101 INIT_WCSLEN;
10102 INIT_WCSCAT;
10103 INIT_WCSDUP;
10104 INIT_WCSXFRM;
10105 INIT___WCSXFRM_L;
10106 INIT_ACCT;
10107 INIT_USER_FROM_UID;
10108 INIT_UID_FROM_USER;
10109 INIT_GROUP_FROM_GID;
10110 INIT_GID_FROM_GROUP;
10111 INIT_ACCESS;
10112 INIT_FACCESSAT;
10113 INIT_GETGROUPLIST;
10114 INIT_GETGROUPMEMBERSHIP;
10115 INIT_READLINK;
10116 INIT_READLINKAT;
10117 INIT_NAME_TO_HANDLE_AT;
10118 INIT_OPEN_BY_HANDLE_AT;
10119 INIT_STRLCPY;
10120 INIT_DEVNAME;
10121 INIT_DEVNAME_R;
10122 INIT_FGETLN;
10123 INIT_STRMODE;
10124 INIT_TTYENT;
10125 INIT_PROTOENT;
10126 INIT_PROTOENT_R;
10127 INIT_NETENT;
10128 INIT_GETMNTINFO;
10129 INIT_MI_VECTOR_HASH;
10130 INIT_SETVBUF;
10131 INIT_GETVFSSTAT;
10132 INIT_REGEX;
10133 INIT_REGEXSUB;
10134 INIT_FTS;
10135 INIT_SYSCTL;
10136 INIT_ASYSCTL;
10137 INIT_SYSCTLGETMIBINFO;
10138 INIT_NL_LANGINFO;
10139 INIT_MODCTL;
10140 INIT_STRTONUM;
10141 INIT_FPARSELN;
10142 INIT_STATVFS1;
10143 INIT_STRTOI;
10144 INIT_CAPSICUM;
10145 INIT_SHA1;
10146 INIT_MD4;
10147 INIT_RMD160;
10148 INIT_MD5;
10149 INIT_FSEEK;
10150 INIT_MD2;
10151 INIT_SHA2;
10152 INIT_VIS;
10153 INIT_CDB;
10154 INIT_GETFSENT;
10155 INIT_ARC4RANDOM;
10156 INIT_POPEN;
10157 INIT_POPENVE;
10158 INIT_PCLOSE;
10159 INIT_FUNOPEN;
10160 INIT_FUNOPEN2;
10161 INIT_FDEVNAME;
10162 INIT_GETUSERSHELL;
10163 INIT_SL_INIT;
10164 INIT_GETRANDOM;
10165 INIT_CRYPT;
10166 INIT_CRYPT_R;
10167 INIT_GETENTROPY;
10168 INIT_QSORT;
10169 INIT_QSORT_R;
10170 INIT_SIGALTSTACK;
10171 INIT_UNAME;
10172 INIT___XUNAME;
10173
10174 INIT___PRINTF_CHK;
10175}
lib/tsan/sanitizer_common/sanitizer_common_interceptors_format.inc created+562
...@@ -0,0 +1,562 @@
1//===-- sanitizer_common_interceptors_format.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// Scanf/printf implementation for use in *Sanitizer interceptors.
10// Follows http://pubs.opengroup.org/onlinepubs/9699919799/functions/fscanf.html
11// and http://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html
12// with a few common GNU extensions.
13//
14//===----------------------------------------------------------------------===//
15
16#include <stdarg.h>
17
18static const char *parse_number(const char *p, int *out) {
19 *out = internal_atoll(p);
20 while (*p >= '0' && *p <= '9')
21 ++p;
22 return p;
23}
24
25static const char *maybe_parse_param_index(const char *p, int *out) {
26 // n$
27 if (*p >= '0' && *p <= '9') {
28 int number;
29 const char *q = parse_number(p, &number);
30 CHECK(q);
31 if (*q == '$') {
32 *out = number;
33 p = q + 1;
34 }
35 }
36
37 // Otherwise, do not change p. This will be re-parsed later as the field
38 // width.
39 return p;
40}
41
42static bool char_is_one_of(char c, const char *s) {
43 return !!internal_strchr(s, c);
44}
45
46static const char *maybe_parse_length_modifier(const char *p, char ll[2]) {
47 if (char_is_one_of(*p, "jztLq")) {
48 ll[0] = *p;
49 ++p;
50 } else if (*p == 'h') {
51 ll[0] = 'h';
52 ++p;
53 if (*p == 'h') {
54 ll[1] = 'h';
55 ++p;
56 }
57 } else if (*p == 'l') {
58 ll[0] = 'l';
59 ++p;
60 if (*p == 'l') {
61 ll[1] = 'l';
62 ++p;
63 }
64 }
65 return p;
66}
67
68// Returns true if the character is an integer conversion specifier.
69static bool format_is_integer_conv(char c) {
70 return char_is_one_of(c, "diouxXn");
71}
72
73// Returns true if the character is an floating point conversion specifier.
74static bool format_is_float_conv(char c) {
75 return char_is_one_of(c, "aAeEfFgG");
76}
77
78// Returns string output character size for string-like conversions,
79// or 0 if the conversion is invalid.
80static int format_get_char_size(char convSpecifier,
81 const char lengthModifier[2]) {
82 if (char_is_one_of(convSpecifier, "CS")) {
83 return sizeof(wchar_t);
84 }
85
86 if (char_is_one_of(convSpecifier, "cs[")) {
87 if (lengthModifier[0] == 'l' && lengthModifier[1] == '\0')
88 return sizeof(wchar_t);
89 else if (lengthModifier[0] == '\0')
90 return sizeof(char);
91 }
92
93 return 0;
94}
95
96enum FormatStoreSize {
97 // Store size not known in advance; can be calculated as wcslen() of the
98 // destination buffer.
99 FSS_WCSLEN = -2,
100 // Store size not known in advance; can be calculated as strlen() of the
101 // destination buffer.
102 FSS_STRLEN = -1,
103 // Invalid conversion specifier.
104 FSS_INVALID = 0
105};
106
107// Returns the memory size of a format directive (if >0), or a value of
108// FormatStoreSize.
109static int format_get_value_size(char convSpecifier,
110 const char lengthModifier[2],
111 bool promote_float) {
112 if (format_is_integer_conv(convSpecifier)) {
113 switch (lengthModifier[0]) {
114 case 'h':
115 return lengthModifier[1] == 'h' ? sizeof(char) : sizeof(short);
116 case 'l':
117 return lengthModifier[1] == 'l' ? sizeof(long long) : sizeof(long);
118 case 'q':
119 return sizeof(long long);
120 case 'L':
121 return sizeof(long long);
122 case 'j':
123 return sizeof(INTMAX_T);
124 case 'z':
125 return sizeof(SIZE_T);
126 case 't':
127 return sizeof(PTRDIFF_T);
128 case 0:
129 return sizeof(int);
130 default:
131 return FSS_INVALID;
132 }
133 }
134
135 if (format_is_float_conv(convSpecifier)) {
136 switch (lengthModifier[0]) {
137 case 'L':
138 case 'q':
139 return sizeof(long double);
140 case 'l':
141 return lengthModifier[1] == 'l' ? sizeof(long double)
142 : sizeof(double);
143 case 0:
144 // Printf promotes floats to doubles but scanf does not
145 return promote_float ? sizeof(double) : sizeof(float);
146 default:
147 return FSS_INVALID;
148 }
149 }
150
151 if (convSpecifier == 'p') {
152 if (lengthModifier[0] != 0)
153 return FSS_INVALID;
154 return sizeof(void *);
155 }
156
157 return FSS_INVALID;
158}
159
160struct ScanfDirective {
161 int argIdx; // argument index, or -1 if not specified ("%n$")
162 int fieldWidth;
163 const char *begin;
164 const char *end;
165 bool suppressed; // suppress assignment ("*")
166 bool allocate; // allocate space ("m")
167 char lengthModifier[2];
168 char convSpecifier;
169 bool maybeGnuMalloc;
170};
171
172// Parse scanf format string. If a valid directive in encountered, it is
173// returned in dir. This function returns the pointer to the first
174// unprocessed character, or 0 in case of error.
175// In case of the end-of-string, a pointer to the closing \0 is returned.
176static const char *scanf_parse_next(const char *p, bool allowGnuMalloc,
177 ScanfDirective *dir) {
178 internal_memset(dir, 0, sizeof(*dir));
179 dir->argIdx = -1;
180
181 while (*p) {
182 if (*p != '%') {
183 ++p;
184 continue;
185 }
186 dir->begin = p;
187 ++p;
188 // %%
189 if (*p == '%') {
190 ++p;
191 continue;
192 }
193 if (*p == '\0') {
194 return nullptr;
195 }
196 // %n$
197 p = maybe_parse_param_index(p, &dir->argIdx);
198 CHECK(p);
199 // *
200 if (*p == '*') {
201 dir->suppressed = true;
202 ++p;
203 }
204 // Field width
205 if (*p >= '0' && *p <= '9') {
206 p = parse_number(p, &dir->fieldWidth);
207 CHECK(p);
208 if (dir->fieldWidth <= 0) // Width if at all must be non-zero
209 return nullptr;
210 }
211 // m
212 if (*p == 'm') {
213 dir->allocate = true;
214 ++p;
215 }
216 // Length modifier.
217 p = maybe_parse_length_modifier(p, dir->lengthModifier);
218 // Conversion specifier.
219 dir->convSpecifier = *p++;
220 // Consume %[...] expression.
221 if (dir->convSpecifier == '[') {
222 if (*p == '^')
223 ++p;
224 if (*p == ']')
225 ++p;
226 while (*p && *p != ']')
227 ++p;
228 if (*p == 0)
229 return nullptr; // unexpected end of string
230 // Consume the closing ']'.
231 ++p;
232 }
233 // This is unfortunately ambiguous between old GNU extension
234 // of %as, %aS and %a[...] and newer POSIX %a followed by
235 // letters s, S or [.
236 if (allowGnuMalloc && dir->convSpecifier == 'a' &&
237 !dir->lengthModifier[0]) {
238 if (*p == 's' || *p == 'S') {
239 dir->maybeGnuMalloc = true;
240 ++p;
241 } else if (*p == '[') {
242 // Watch for %a[h-j%d], if % appears in the
243 // [...] range, then we need to give up, we don't know
244 // if scanf will parse it as POSIX %a [h-j %d ] or
245 // GNU allocation of string with range dh-j plus %.
246 const char *q = p + 1;
247 if (*q == '^')
248 ++q;
249 if (*q == ']')
250 ++q;
251 while (*q && *q != ']' && *q != '%')
252 ++q;
253 if (*q == 0 || *q == '%')
254 return nullptr;
255 p = q + 1; // Consume the closing ']'.
256 dir->maybeGnuMalloc = true;
257 }
258 }
259 dir->end = p;
260 break;
261 }
262 return p;
263}
264
265static int scanf_get_value_size(ScanfDirective *dir) {
266 if (dir->allocate) {
267 if (!char_is_one_of(dir->convSpecifier, "cCsS["))
268 return FSS_INVALID;
269 return sizeof(char *);
270 }
271
272 if (dir->maybeGnuMalloc) {
273 if (dir->convSpecifier != 'a' || dir->lengthModifier[0])
274 return FSS_INVALID;
275 // This is ambiguous, so check the smaller size of char * (if it is
276 // a GNU extension of %as, %aS or %a[...]) and float (if it is
277 // POSIX %a followed by s, S or [ letters).
278 return sizeof(char *) < sizeof(float) ? sizeof(char *) : sizeof(float);
279 }
280
281 if (char_is_one_of(dir->convSpecifier, "cCsS[")) {
282 bool needsTerminator = char_is_one_of(dir->convSpecifier, "sS[");
283 unsigned charSize =
284 format_get_char_size(dir->convSpecifier, dir->lengthModifier);
285 if (charSize == 0)
286 return FSS_INVALID;
287 if (dir->fieldWidth == 0) {
288 if (!needsTerminator)
289 return charSize;
290 return (charSize == sizeof(char)) ? FSS_STRLEN : FSS_WCSLEN;
291 }
292 return (dir->fieldWidth + needsTerminator) * charSize;
293 }
294
295 return format_get_value_size(dir->convSpecifier, dir->lengthModifier, false);
296}
297
298// Common part of *scanf interceptors.
299// Process format string and va_list, and report all store ranges.
300// Stops when "consuming" n_inputs input items.
301static void scanf_common(void *ctx, int n_inputs, bool allowGnuMalloc,
302 const char *format, va_list aq) {
303 CHECK_GT(n_inputs, 0);
304 const char *p = format;
305
306 COMMON_INTERCEPTOR_READ_RANGE(ctx, format, internal_strlen(format) + 1);
307
308 while (*p) {
309 ScanfDirective dir;
310 p = scanf_parse_next(p, allowGnuMalloc, &dir);
311 if (!p)
312 break;
313 if (dir.convSpecifier == 0) {
314 // This can only happen at the end of the format string.
315 CHECK_EQ(*p, 0);
316 break;
317 }
318 // Here the directive is valid. Do what it says.
319 if (dir.argIdx != -1) {
320 // Unsupported.
321 break;
322 }
323 if (dir.suppressed)
324 continue;
325 int size = scanf_get_value_size(&dir);
326 if (size == FSS_INVALID) {
327 Report("%s: WARNING: unexpected format specifier in scanf interceptor: ",
328 SanitizerToolName, "%.*s\n", dir.end - dir.begin, dir.begin);
329 break;
330 }
331 void *argp = va_arg(aq, void *);
332 if (dir.convSpecifier != 'n')
333 --n_inputs;
334 if (n_inputs < 0)
335 break;
336 if (size == FSS_STRLEN) {
337 size = internal_strlen((const char *)argp) + 1;
338 } else if (size == FSS_WCSLEN) {
339 // FIXME: actually use wcslen() to calculate it.
340 size = 0;
341 }
342 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, argp, size);
343 }
344}
345
346#if SANITIZER_INTERCEPT_PRINTF
347
348struct PrintfDirective {
349 int fieldWidth;
350 int fieldPrecision;
351 int argIdx; // width argument index, or -1 if not specified ("%*n$")
352 int precisionIdx; // precision argument index, or -1 if not specified (".*n$")
353 const char *begin;
354 const char *end;
355 bool starredWidth;
356 bool starredPrecision;
357 char lengthModifier[2];
358 char convSpecifier;
359};
360
361static const char *maybe_parse_number(const char *p, int *out) {
362 if (*p >= '0' && *p <= '9')
363 p = parse_number(p, out);
364 return p;
365}
366
367static const char *maybe_parse_number_or_star(const char *p, int *out,
368 bool *star) {
369 if (*p == '*') {
370 *star = true;
371 ++p;
372 } else {
373 *star = false;
374 p = maybe_parse_number(p, out);
375 }
376 return p;
377}
378
379// Parse printf format string. Same as scanf_parse_next.
380static const char *printf_parse_next(const char *p, PrintfDirective *dir) {
381 internal_memset(dir, 0, sizeof(*dir));
382 dir->argIdx = -1;
383 dir->precisionIdx = -1;
384
385 while (*p) {
386 if (*p != '%') {
387 ++p;
388 continue;
389 }
390 dir->begin = p;
391 ++p;
392 // %%
393 if (*p == '%') {
394 ++p;
395 continue;
396 }
397 if (*p == '\0') {
398 return nullptr;
399 }
400 // %n$
401 p = maybe_parse_param_index(p, &dir->precisionIdx);
402 CHECK(p);
403 // Flags
404 while (char_is_one_of(*p, "'-+ #0")) {
405 ++p;
406 }
407 // Field width
408 p = maybe_parse_number_or_star(p, &dir->fieldWidth,
409 &dir->starredWidth);
410 if (!p)
411 return nullptr;
412 // Precision
413 if (*p == '.') {
414 ++p;
415 // Actual precision is optional (surprise!)
416 p = maybe_parse_number_or_star(p, &dir->fieldPrecision,
417 &dir->starredPrecision);
418 if (!p)
419 return nullptr;
420 // m$
421 if (dir->starredPrecision) {
422 p = maybe_parse_param_index(p, &dir->precisionIdx);
423 CHECK(p);
424 }
425 }
426 // Length modifier.
427 p = maybe_parse_length_modifier(p, dir->lengthModifier);
428 // Conversion specifier.
429 dir->convSpecifier = *p++;
430 dir->end = p;
431 break;
432 }
433 return p;
434}
435
436static int printf_get_value_size(PrintfDirective *dir) {
437 if (char_is_one_of(dir->convSpecifier, "cCsS")) {
438 unsigned charSize =
439 format_get_char_size(dir->convSpecifier, dir->lengthModifier);
440 if (charSize == 0)
441 return FSS_INVALID;
442 if (char_is_one_of(dir->convSpecifier, "sS")) {
443 return (charSize == sizeof(char)) ? FSS_STRLEN : FSS_WCSLEN;
444 }
445 return charSize;
446 }
447
448 return format_get_value_size(dir->convSpecifier, dir->lengthModifier, true);
449}
450
451#define SKIP_SCALAR_ARG(aq, convSpecifier, size) \
452 do { \
453 if (format_is_float_conv(convSpecifier)) { \
454 switch (size) { \
455 case 8: \
456 va_arg(*aq, double); \
457 break; \
458 case 12: \
459 va_arg(*aq, long double); \
460 break; \
461 case 16: \
462 va_arg(*aq, long double); \
463 break; \
464 default: \
465 Report("WARNING: unexpected floating-point arg size" \
466 " in printf interceptor: %d\n", size); \
467 return; \
468 } \
469 } else { \
470 switch (size) { \
471 case 1: \
472 case 2: \
473 case 4: \
474 va_arg(*aq, u32); \
475 break; \
476 case 8: \
477 va_arg(*aq, u64); \
478 break; \
479 default: \
480 Report("WARNING: unexpected arg size" \
481 " in printf interceptor: %d\n", size); \
482 return; \
483 } \
484 } \
485 } while (0)
486
487// Common part of *printf interceptors.
488// Process format string and va_list, and report all load ranges.
489static void printf_common(void *ctx, const char *format, va_list aq) {
490 COMMON_INTERCEPTOR_READ_RANGE(ctx, format, internal_strlen(format) + 1);
491
492 const char *p = format;
493
494 while (*p) {
495 PrintfDirective dir;
496 p = printf_parse_next(p, &dir);
497 if (!p)
498 break;
499 if (dir.convSpecifier == 0) {
500 // This can only happen at the end of the format string.
501 CHECK_EQ(*p, 0);
502 break;
503 }
504 // Here the directive is valid. Do what it says.
505 if (dir.argIdx != -1 || dir.precisionIdx != -1) {
506 // Unsupported.
507 break;
508 }
509 if (dir.starredWidth) {
510 // Dynamic width
511 SKIP_SCALAR_ARG(&aq, 'd', sizeof(int));
512 }
513 if (dir.starredPrecision) {
514 // Dynamic precision
515 SKIP_SCALAR_ARG(&aq, 'd', sizeof(int));
516 }
517 // %m does not require an argument: strlen(errno).
518 if (dir.convSpecifier == 'm')
519 continue;
520 int size = printf_get_value_size(&dir);
521 if (size == FSS_INVALID) {
522 static int ReportedOnce;
523 if (!ReportedOnce++)
524 Report(
525 "%s: WARNING: unexpected format specifier in printf "
526 "interceptor: %.*s (reported once per process)\n",
527 SanitizerToolName, dir.end - dir.begin, dir.begin);
528 break;
529 }
530 if (dir.convSpecifier == 'n') {
531 void *argp = va_arg(aq, void *);
532 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, argp, size);
533 continue;
534 } else if (size == FSS_STRLEN) {
535 if (void *argp = va_arg(aq, void *)) {
536 if (dir.starredPrecision) {
537 // FIXME: properly support starred precision for strings.
538 size = 0;
539 } else if (dir.fieldPrecision > 0) {
540 // Won't read more than "precision" symbols.
541 size = internal_strnlen((const char *)argp, dir.fieldPrecision);
542 if (size < dir.fieldPrecision) size++;
543 } else {
544 // Whole string will be accessed.
545 size = internal_strlen((const char *)argp) + 1;
546 }
547 COMMON_INTERCEPTOR_READ_RANGE(ctx, argp, size);
548 }
549 } else if (size == FSS_WCSLEN) {
550 if (void *argp = va_arg(aq, void *)) {
551 // FIXME: Properly support wide-character strings (via wcsrtombs).
552 size = 0;
553 COMMON_INTERCEPTOR_READ_RANGE(ctx, argp, size);
554 }
555 } else {
556 // Skip non-pointer args
557 SKIP_SCALAR_ARG(&aq, dir.convSpecifier, size);
558 }
559 }
560}
561
562#endif // SANITIZER_INTERCEPT_PRINTF
lib/tsan/sanitizer_common/sanitizer_common_interceptors_ioctl.inc created+609
...@@ -0,0 +1,609 @@
1//===-- sanitizer_common_interceptors_ioctl.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// Ioctl handling in common sanitizer interceptors.
10//===----------------------------------------------------------------------===//
11
12#if !SANITIZER_NETBSD
13
14#include "sanitizer_flags.h"
15
16struct ioctl_desc {
17 unsigned req;
18 // FIXME: support read+write arguments. Currently READWRITE and WRITE do the
19 // same thing.
20 // XXX: The declarations below may use WRITE instead of READWRITE, unless
21 // explicitly noted.
22 enum {
23 NONE,
24 READ,
25 WRITE,
26 READWRITE,
27 CUSTOM
28 } type : 3;
29 unsigned size : 29;
30 const char* name;
31};
32
33const unsigned ioctl_table_max = 500;
34static ioctl_desc ioctl_table[ioctl_table_max];
35static unsigned ioctl_table_size = 0;
36
37// This can not be declared as a global, because references to struct_*_sz
38// require a global initializer. And this table must be available before global
39// initializers are run.
40static void ioctl_table_fill() {
41#define _(rq, tp, sz) \
42 if (IOCTL_##rq != IOCTL_NOT_PRESENT) { \
43 CHECK(ioctl_table_size < ioctl_table_max); \
44 ioctl_table[ioctl_table_size].req = IOCTL_##rq; \
45 ioctl_table[ioctl_table_size].type = ioctl_desc::tp; \
46 ioctl_table[ioctl_table_size].size = sz; \
47 ioctl_table[ioctl_table_size].name = #rq; \
48 ++ioctl_table_size; \
49 }
50
51 _(FIOASYNC, READ, sizeof(int));
52 _(FIOCLEX, NONE, 0);
53 _(FIOGETOWN, WRITE, sizeof(int));
54 _(FIONBIO, READ, sizeof(int));
55 _(FIONCLEX, NONE, 0);
56 _(FIOSETOWN, READ, sizeof(int));
57 _(SIOCATMARK, WRITE, sizeof(int));
58 _(SIOCGIFCONF, CUSTOM, 0);
59 _(SIOCGPGRP, WRITE, sizeof(int));
60 _(SIOCSPGRP, READ, sizeof(int));
61#if !SANITIZER_SOLARIS
62 _(TIOCCONS, NONE, 0);
63#endif
64 _(TIOCEXCL, NONE, 0);
65 _(TIOCGETD, WRITE, sizeof(int));
66 _(TIOCGPGRP, WRITE, pid_t_sz);
67 _(TIOCGWINSZ, WRITE, struct_winsize_sz);
68 _(TIOCMBIC, READ, sizeof(int));
69 _(TIOCMBIS, READ, sizeof(int));
70 _(TIOCMGET, WRITE, sizeof(int));
71 _(TIOCMSET, READ, sizeof(int));
72 _(TIOCNOTTY, NONE, 0);
73 _(TIOCNXCL, NONE, 0);
74 _(TIOCOUTQ, WRITE, sizeof(int));
75 _(TIOCPKT, READ, sizeof(int));
76 _(TIOCSCTTY, NONE, 0);
77 _(TIOCSETD, READ, sizeof(int));
78 _(TIOCSPGRP, READ, pid_t_sz);
79 _(TIOCSTI, READ, sizeof(char));
80 _(TIOCSWINSZ, READ, struct_winsize_sz);
81
82#if !SANITIZER_IOS
83 _(SIOCADDMULTI, READ, struct_ifreq_sz);
84 _(SIOCDELMULTI, READ, struct_ifreq_sz);
85 _(SIOCGIFADDR, WRITE, struct_ifreq_sz);
86 _(SIOCGIFBRDADDR, WRITE, struct_ifreq_sz);
87 _(SIOCGIFDSTADDR, WRITE, struct_ifreq_sz);
88 _(SIOCGIFFLAGS, WRITE, struct_ifreq_sz);
89 _(SIOCGIFMETRIC, WRITE, struct_ifreq_sz);
90 _(SIOCGIFMTU, WRITE, struct_ifreq_sz);
91 _(SIOCGIFNETMASK, WRITE, struct_ifreq_sz);
92 _(SIOCSIFADDR, READ, struct_ifreq_sz);
93 _(SIOCSIFBRDADDR, READ, struct_ifreq_sz);
94 _(SIOCSIFDSTADDR, READ, struct_ifreq_sz);
95 _(SIOCSIFFLAGS, READ, struct_ifreq_sz);
96 _(SIOCSIFMETRIC, READ, struct_ifreq_sz);
97 _(SIOCSIFMTU, READ, struct_ifreq_sz);
98 _(SIOCSIFNETMASK, READ, struct_ifreq_sz);
99#endif
100
101#if (SANITIZER_LINUX && !SANITIZER_ANDROID)
102 _(SIOCGETSGCNT, WRITE, struct_sioc_sg_req_sz);
103 _(SIOCGETVIFCNT, WRITE, struct_sioc_vif_req_sz);
104#endif
105
106#if SANITIZER_LINUX
107 // Conflicting request ids.
108 // _(CDROMAUDIOBUFSIZ, NONE, 0);
109 // _(SNDCTL_TMR_CONTINUE, NONE, 0);
110 // _(SNDCTL_TMR_START, NONE, 0);
111 // _(SNDCTL_TMR_STOP, NONE, 0);
112 // _(SOUND_MIXER_READ_LOUD, WRITE, sizeof(int)); // same as ...READ_ENHANCE
113 // _(SOUND_MIXER_READ_MUTE, WRITE, sizeof(int)); // same as ...READ_ENHANCE
114 // _(SOUND_MIXER_WRITE_LOUD, WRITE, sizeof(int)); // same as ...WRITE_ENHANCE
115 // _(SOUND_MIXER_WRITE_MUTE, WRITE, sizeof(int)); // same as ...WRITE_ENHANCE
116 _(BLKFLSBUF, NONE, 0);
117 _(BLKGETSIZE, WRITE, sizeof(uptr));
118 _(BLKRAGET, WRITE, sizeof(int));
119 _(BLKRASET, NONE, 0);
120 _(BLKROGET, WRITE, sizeof(int));
121 _(BLKROSET, READ, sizeof(int));
122 _(BLKRRPART, NONE, 0);
123 _(CDROMEJECT, NONE, 0);
124 _(CDROMEJECT_SW, NONE, 0);
125 _(CDROMMULTISESSION, WRITE, struct_cdrom_multisession_sz);
126 _(CDROMPAUSE, NONE, 0);
127 _(CDROMPLAYMSF, READ, struct_cdrom_msf_sz);
128 _(CDROMPLAYTRKIND, READ, struct_cdrom_ti_sz);
129 _(CDROMREADAUDIO, READ, struct_cdrom_read_audio_sz);
130 _(CDROMREADCOOKED, READ, struct_cdrom_msf_sz);
131 _(CDROMREADMODE1, READ, struct_cdrom_msf_sz);
132 _(CDROMREADMODE2, READ, struct_cdrom_msf_sz);
133 _(CDROMREADRAW, READ, struct_cdrom_msf_sz);
134 _(CDROMREADTOCENTRY, WRITE, struct_cdrom_tocentry_sz);
135 _(CDROMREADTOCHDR, WRITE, struct_cdrom_tochdr_sz);
136 _(CDROMRESET, NONE, 0);
137 _(CDROMRESUME, NONE, 0);
138 _(CDROMSEEK, READ, struct_cdrom_msf_sz);
139 _(CDROMSTART, NONE, 0);
140 _(CDROMSTOP, NONE, 0);
141 _(CDROMSUBCHNL, WRITE, struct_cdrom_subchnl_sz);
142 _(CDROMVOLCTRL, READ, struct_cdrom_volctrl_sz);
143 _(CDROMVOLREAD, WRITE, struct_cdrom_volctrl_sz);
144 _(CDROM_GET_UPC, WRITE, 8);
145 _(EVIOCGABS, WRITE, struct_input_absinfo_sz); // fixup
146 _(EVIOCGBIT, WRITE, struct_input_id_sz); // fixup
147 _(EVIOCGEFFECTS, WRITE, sizeof(int));
148 _(EVIOCGID, WRITE, struct_input_id_sz);
149 _(EVIOCGKEY, WRITE, 0);
150 _(EVIOCGKEYCODE, WRITE, sizeof(int) * 2);
151 _(EVIOCGLED, WRITE, 0);
152 _(EVIOCGNAME, WRITE, 0);
153 _(EVIOCGPHYS, WRITE, 0);
154 _(EVIOCGRAB, READ, sizeof(int));
155 _(EVIOCGREP, WRITE, sizeof(int) * 2);
156 _(EVIOCGSND, WRITE, 0);
157 _(EVIOCGSW, WRITE, 0);
158 _(EVIOCGUNIQ, WRITE, 0);
159 _(EVIOCGVERSION, WRITE, sizeof(int));
160 _(EVIOCRMFF, READ, sizeof(int));
161 _(EVIOCSABS, READ, struct_input_absinfo_sz); // fixup
162 _(EVIOCSFF, READ, struct_ff_effect_sz);
163 _(EVIOCSKEYCODE, READ, sizeof(int) * 2);
164 _(EVIOCSREP, READ, sizeof(int) * 2);
165 _(FDCLRPRM, NONE, 0);
166 _(FDDEFPRM, READ, struct_floppy_struct_sz);
167 _(FDFLUSH, NONE, 0);
168 _(FDFMTBEG, NONE, 0);
169 _(FDFMTEND, NONE, 0);
170 _(FDFMTTRK, READ, struct_format_descr_sz);
171 _(FDGETDRVPRM, WRITE, struct_floppy_drive_params_sz);
172 _(FDGETDRVSTAT, WRITE, struct_floppy_drive_struct_sz);
173 _(FDGETDRVTYP, WRITE, 16);
174 _(FDGETFDCSTAT, WRITE, struct_floppy_fdc_state_sz);
175 _(FDGETMAXERRS, WRITE, struct_floppy_max_errors_sz);
176 _(FDGETPRM, WRITE, struct_floppy_struct_sz);
177 _(FDMSGOFF, NONE, 0);
178 _(FDMSGON, NONE, 0);
179 _(FDPOLLDRVSTAT, WRITE, struct_floppy_drive_struct_sz);
180 _(FDRAWCMD, WRITE, struct_floppy_raw_cmd_sz);
181 _(FDRESET, NONE, 0);
182 _(FDSETDRVPRM, READ, struct_floppy_drive_params_sz);
183 _(FDSETEMSGTRESH, NONE, 0);
184 _(FDSETMAXERRS, READ, struct_floppy_max_errors_sz);
185 _(FDSETPRM, READ, struct_floppy_struct_sz);
186 _(FDTWADDLE, NONE, 0);
187 _(FDWERRORCLR, NONE, 0);
188 _(FDWERRORGET, WRITE, struct_floppy_write_errors_sz);
189 _(HDIO_DRIVE_CMD, WRITE, sizeof(int));
190 _(HDIO_GETGEO, WRITE, struct_hd_geometry_sz);
191 _(HDIO_GET_32BIT, WRITE, sizeof(int));
192 _(HDIO_GET_DMA, WRITE, sizeof(int));
193 _(HDIO_GET_IDENTITY, WRITE, struct_hd_driveid_sz);
194 _(HDIO_GET_KEEPSETTINGS, WRITE, sizeof(int));
195 _(HDIO_GET_MULTCOUNT, WRITE, sizeof(int));
196 _(HDIO_GET_NOWERR, WRITE, sizeof(int));
197 _(HDIO_GET_UNMASKINTR, WRITE, sizeof(int));
198 _(HDIO_SET_32BIT, NONE, 0);
199 _(HDIO_SET_DMA, NONE, 0);
200 _(HDIO_SET_KEEPSETTINGS, NONE, 0);
201 _(HDIO_SET_MULTCOUNT, NONE, 0);
202 _(HDIO_SET_NOWERR, NONE, 0);
203 _(HDIO_SET_UNMASKINTR, NONE, 0);
204 _(MTIOCGET, WRITE, struct_mtget_sz);
205 _(MTIOCPOS, WRITE, struct_mtpos_sz);
206 _(MTIOCTOP, READ, struct_mtop_sz);
207 _(PPPIOCGASYNCMAP, WRITE, sizeof(int));
208 _(PPPIOCGDEBUG, WRITE, sizeof(int));
209 _(PPPIOCGFLAGS, WRITE, sizeof(int));
210 _(PPPIOCGUNIT, WRITE, sizeof(int));
211 _(PPPIOCGXASYNCMAP, WRITE, sizeof(int) * 8);
212 _(PPPIOCSASYNCMAP, READ, sizeof(int));
213 _(PPPIOCSDEBUG, READ, sizeof(int));
214 _(PPPIOCSFLAGS, READ, sizeof(int));
215 _(PPPIOCSMAXCID, READ, sizeof(int));
216 _(PPPIOCSMRU, READ, sizeof(int));
217 _(PPPIOCSXASYNCMAP, READ, sizeof(int) * 8);
218 _(SIOCADDRT, READ, struct_rtentry_sz);
219 _(SIOCDARP, READ, struct_arpreq_sz);
220 _(SIOCDELRT, READ, struct_rtentry_sz);
221 _(SIOCDRARP, READ, struct_arpreq_sz);
222 _(SIOCGARP, WRITE, struct_arpreq_sz);
223 _(SIOCGIFENCAP, WRITE, sizeof(int));
224 _(SIOCGIFHWADDR, WRITE, struct_ifreq_sz);
225 _(SIOCGIFMAP, WRITE, struct_ifreq_sz);
226 _(SIOCGIFMEM, WRITE, struct_ifreq_sz);
227 _(SIOCGIFNAME, NONE, 0);
228 _(SIOCGIFSLAVE, NONE, 0);
229 _(SIOCGRARP, WRITE, struct_arpreq_sz);
230 _(SIOCGSTAMP, WRITE, timeval_sz);
231 _(SIOCSARP, READ, struct_arpreq_sz);
232 _(SIOCSIFENCAP, READ, sizeof(int));
233 _(SIOCSIFHWADDR, READ, struct_ifreq_sz);
234 _(SIOCSIFLINK, NONE, 0);
235 _(SIOCSIFMAP, READ, struct_ifreq_sz);
236 _(SIOCSIFMEM, READ, struct_ifreq_sz);
237 _(SIOCSIFSLAVE, NONE, 0);
238 _(SIOCSRARP, READ, struct_arpreq_sz);
239 _(SNDCTL_COPR_HALT, WRITE, struct_copr_debug_buf_sz);
240 _(SNDCTL_COPR_LOAD, READ, struct_copr_buffer_sz);
241 _(SNDCTL_COPR_RCODE, WRITE, struct_copr_debug_buf_sz);
242 _(SNDCTL_COPR_RCVMSG, WRITE, struct_copr_msg_sz);
243 _(SNDCTL_COPR_RDATA, WRITE, struct_copr_debug_buf_sz);
244 _(SNDCTL_COPR_RESET, NONE, 0);
245 _(SNDCTL_COPR_RUN, WRITE, struct_copr_debug_buf_sz);
246 _(SNDCTL_COPR_SENDMSG, READ, struct_copr_msg_sz);
247 _(SNDCTL_COPR_WCODE, READ, struct_copr_debug_buf_sz);
248 _(SNDCTL_COPR_WDATA, READ, struct_copr_debug_buf_sz);
249 _(SNDCTL_DSP_GETBLKSIZE, WRITE, sizeof(int));
250 _(SNDCTL_DSP_GETFMTS, WRITE, sizeof(int));
251 _(SNDCTL_DSP_NONBLOCK, NONE, 0);
252 _(SNDCTL_DSP_POST, NONE, 0);
253 _(SNDCTL_DSP_RESET, NONE, 0);
254 _(SNDCTL_DSP_SETFMT, WRITE, sizeof(int));
255 _(SNDCTL_DSP_SETFRAGMENT, WRITE, sizeof(int));
256 _(SNDCTL_DSP_SPEED, WRITE, sizeof(int));
257 _(SNDCTL_DSP_STEREO, WRITE, sizeof(int));
258 _(SNDCTL_DSP_SUBDIVIDE, WRITE, sizeof(int));
259 _(SNDCTL_DSP_SYNC, NONE, 0);
260 _(SNDCTL_FM_4OP_ENABLE, READ, sizeof(int));
261 _(SNDCTL_FM_LOAD_INSTR, READ, struct_sbi_instrument_sz);
262 _(SNDCTL_MIDI_INFO, WRITE, struct_midi_info_sz);
263 _(SNDCTL_MIDI_PRETIME, WRITE, sizeof(int));
264 _(SNDCTL_SEQ_CTRLRATE, WRITE, sizeof(int));
265 _(SNDCTL_SEQ_GETINCOUNT, WRITE, sizeof(int));
266 _(SNDCTL_SEQ_GETOUTCOUNT, WRITE, sizeof(int));
267 _(SNDCTL_SEQ_NRMIDIS, WRITE, sizeof(int));
268 _(SNDCTL_SEQ_NRSYNTHS, WRITE, sizeof(int));
269 _(SNDCTL_SEQ_OUTOFBAND, READ, struct_seq_event_rec_sz);
270 _(SNDCTL_SEQ_PANIC, NONE, 0);
271 _(SNDCTL_SEQ_PERCMODE, NONE, 0);
272 _(SNDCTL_SEQ_RESET, NONE, 0);
273 _(SNDCTL_SEQ_RESETSAMPLES, READ, sizeof(int));
274 _(SNDCTL_SEQ_SYNC, NONE, 0);
275 _(SNDCTL_SEQ_TESTMIDI, READ, sizeof(int));
276 _(SNDCTL_SEQ_THRESHOLD, READ, sizeof(int));
277 _(SNDCTL_SYNTH_INFO, WRITE, struct_synth_info_sz);
278 _(SNDCTL_SYNTH_MEMAVL, WRITE, sizeof(int));
279 _(SNDCTL_TMR_METRONOME, READ, sizeof(int));
280 _(SNDCTL_TMR_SELECT, WRITE, sizeof(int));
281 _(SNDCTL_TMR_SOURCE, WRITE, sizeof(int));
282 _(SNDCTL_TMR_TEMPO, WRITE, sizeof(int));
283 _(SNDCTL_TMR_TIMEBASE, WRITE, sizeof(int));
284 _(SOUND_MIXER_READ_ALTPCM, WRITE, sizeof(int));
285 _(SOUND_MIXER_READ_BASS, WRITE, sizeof(int));
286 _(SOUND_MIXER_READ_CAPS, WRITE, sizeof(int));
287 _(SOUND_MIXER_READ_CD, WRITE, sizeof(int));
288 _(SOUND_MIXER_READ_DEVMASK, WRITE, sizeof(int));
289 _(SOUND_MIXER_READ_ENHANCE, WRITE, sizeof(int));
290 _(SOUND_MIXER_READ_IGAIN, WRITE, sizeof(int));
291 _(SOUND_MIXER_READ_IMIX, WRITE, sizeof(int));
292 _(SOUND_MIXER_READ_LINE, WRITE, sizeof(int));
293 _(SOUND_MIXER_READ_LINE1, WRITE, sizeof(int));
294 _(SOUND_MIXER_READ_LINE2, WRITE, sizeof(int));
295 _(SOUND_MIXER_READ_LINE3, WRITE, sizeof(int));
296 _(SOUND_MIXER_READ_MIC, WRITE, sizeof(int));
297 _(SOUND_MIXER_READ_OGAIN, WRITE, sizeof(int));
298 _(SOUND_MIXER_READ_PCM, WRITE, sizeof(int));
299 _(SOUND_MIXER_READ_RECLEV, WRITE, sizeof(int));
300 _(SOUND_MIXER_READ_RECMASK, WRITE, sizeof(int));
301 _(SOUND_MIXER_READ_RECSRC, WRITE, sizeof(int));
302 _(SOUND_MIXER_READ_SPEAKER, WRITE, sizeof(int));
303 _(SOUND_MIXER_READ_STEREODEVS, WRITE, sizeof(int));
304 _(SOUND_MIXER_READ_SYNTH, WRITE, sizeof(int));
305 _(SOUND_MIXER_READ_TREBLE, WRITE, sizeof(int));
306 _(SOUND_MIXER_READ_VOLUME, WRITE, sizeof(int));
307 _(SOUND_MIXER_WRITE_ALTPCM, WRITE, sizeof(int));
308 _(SOUND_MIXER_WRITE_BASS, WRITE, sizeof(int));
309 _(SOUND_MIXER_WRITE_CD, WRITE, sizeof(int));
310 _(SOUND_MIXER_WRITE_ENHANCE, WRITE, sizeof(int));
311 _(SOUND_MIXER_WRITE_IGAIN, WRITE, sizeof(int));
312 _(SOUND_MIXER_WRITE_IMIX, WRITE, sizeof(int));
313 _(SOUND_MIXER_WRITE_LINE, WRITE, sizeof(int));
314 _(SOUND_MIXER_WRITE_LINE1, WRITE, sizeof(int));
315 _(SOUND_MIXER_WRITE_LINE2, WRITE, sizeof(int));
316 _(SOUND_MIXER_WRITE_LINE3, WRITE, sizeof(int));
317 _(SOUND_MIXER_WRITE_MIC, WRITE, sizeof(int));
318 _(SOUND_MIXER_WRITE_OGAIN, WRITE, sizeof(int));
319 _(SOUND_MIXER_WRITE_PCM, WRITE, sizeof(int));
320 _(SOUND_MIXER_WRITE_RECLEV, WRITE, sizeof(int));
321 _(SOUND_MIXER_WRITE_RECSRC, WRITE, sizeof(int));
322 _(SOUND_MIXER_WRITE_SPEAKER, WRITE, sizeof(int));
323 _(SOUND_MIXER_WRITE_SYNTH, WRITE, sizeof(int));
324 _(SOUND_MIXER_WRITE_TREBLE, WRITE, sizeof(int));
325 _(SOUND_MIXER_WRITE_VOLUME, WRITE, sizeof(int));
326 _(SOUND_PCM_READ_BITS, WRITE, sizeof(int));
327 _(SOUND_PCM_READ_CHANNELS, WRITE, sizeof(int));
328 _(SOUND_PCM_READ_FILTER, WRITE, sizeof(int));
329 _(SOUND_PCM_READ_RATE, WRITE, sizeof(int));
330 _(SOUND_PCM_WRITE_CHANNELS, WRITE, sizeof(int));
331 _(SOUND_PCM_WRITE_FILTER, WRITE, sizeof(int));
332 _(TCFLSH, NONE, 0);
333 _(TCGETA, WRITE, struct_termio_sz);
334 _(TCGETS, WRITE, struct_termios_sz);
335 _(TCSBRK, NONE, 0);
336 _(TCSBRKP, NONE, 0);
337 _(TCSETA, READ, struct_termio_sz);
338 _(TCSETAF, READ, struct_termio_sz);
339 _(TCSETAW, READ, struct_termio_sz);
340 _(TCSETS, READ, struct_termios_sz);
341 _(TCSETSF, READ, struct_termios_sz);
342 _(TCSETSW, READ, struct_termios_sz);
343 _(TCXONC, NONE, 0);
344 _(TIOCGLCKTRMIOS, WRITE, struct_termios_sz);
345 _(TIOCGSOFTCAR, WRITE, sizeof(int));
346 _(TIOCINQ, WRITE, sizeof(int));
347 _(TIOCLINUX, READ, sizeof(char));
348 _(TIOCSERCONFIG, NONE, 0);
349 _(TIOCSERGETLSR, WRITE, sizeof(int));
350 _(TIOCSERGWILD, WRITE, sizeof(int));
351 _(TIOCSERSWILD, READ, sizeof(int));
352 _(TIOCSLCKTRMIOS, READ, struct_termios_sz);
353 _(TIOCSSOFTCAR, READ, sizeof(int));
354 _(VT_ACTIVATE, NONE, 0);
355 _(VT_DISALLOCATE, NONE, 0);
356 _(VT_GETMODE, WRITE, struct_vt_mode_sz);
357 _(VT_GETSTATE, WRITE, struct_vt_stat_sz);
358 _(VT_OPENQRY, WRITE, sizeof(int));
359 _(VT_RELDISP, NONE, 0);
360 _(VT_RESIZE, READ, struct_vt_sizes_sz);
361 _(VT_RESIZEX, READ, struct_vt_consize_sz);
362 _(VT_SENDSIG, NONE, 0);
363 _(VT_SETMODE, READ, struct_vt_mode_sz);
364 _(VT_WAITACTIVE, NONE, 0);
365#endif
366
367#if SANITIZER_LINUX && !SANITIZER_ANDROID
368 // _(SIOCDEVPLIP, WRITE, struct_ifreq_sz); // the same as EQL_ENSLAVE
369 _(CYGETDEFTHRESH, WRITE, sizeof(int));
370 _(CYGETDEFTIMEOUT, WRITE, sizeof(int));
371 _(CYGETMON, WRITE, struct_cyclades_monitor_sz);
372 _(CYGETTHRESH, WRITE, sizeof(int));
373 _(CYGETTIMEOUT, WRITE, sizeof(int));
374 _(CYSETDEFTHRESH, NONE, 0);
375 _(CYSETDEFTIMEOUT, NONE, 0);
376 _(CYSETTHRESH, NONE, 0);
377 _(CYSETTIMEOUT, NONE, 0);
378 _(EQL_EMANCIPATE, WRITE, struct_ifreq_sz);
379 _(EQL_ENSLAVE, WRITE, struct_ifreq_sz);
380 _(EQL_GETMASTRCFG, WRITE, struct_ifreq_sz);
381 _(EQL_GETSLAVECFG, WRITE, struct_ifreq_sz);
382 _(EQL_SETMASTRCFG, WRITE, struct_ifreq_sz);
383 _(EQL_SETSLAVECFG, WRITE, struct_ifreq_sz);
384 _(EVIOCGKEYCODE_V2, WRITE, struct_input_keymap_entry_sz);
385 _(EVIOCGPROP, WRITE, 0);
386 _(EVIOCSKEYCODE_V2, READ, struct_input_keymap_entry_sz);
387 _(FS_IOC_GETFLAGS, WRITE, sizeof(int));
388 _(FS_IOC_GETVERSION, WRITE, sizeof(int));
389 _(FS_IOC_SETFLAGS, READ, sizeof(int));
390 _(FS_IOC_SETVERSION, READ, sizeof(int));
391 _(GIO_CMAP, WRITE, 48);
392 _(GIO_FONT, WRITE, 8192);
393 _(GIO_SCRNMAP, WRITE, e_tabsz);
394 _(GIO_UNIMAP, WRITE, struct_unimapdesc_sz);
395 _(GIO_UNISCRNMAP, WRITE, sizeof(short) * e_tabsz);
396 _(KDADDIO, NONE, 0);
397 _(KDDELIO, NONE, 0);
398 _(KDDISABIO, NONE, 0);
399 _(KDENABIO, NONE, 0);
400 _(KDGETKEYCODE, WRITE, struct_kbkeycode_sz);
401 _(KDGETLED, WRITE, 1);
402 _(KDGETMODE, WRITE, sizeof(int));
403 _(KDGKBDIACR, WRITE, struct_kbdiacrs_sz);
404 _(KDGKBENT, WRITE, struct_kbentry_sz);
405 _(KDGKBLED, WRITE, sizeof(int));
406 _(KDGKBMETA, WRITE, sizeof(int));
407 _(KDGKBMODE, WRITE, sizeof(int));
408 _(KDGKBSENT, WRITE, struct_kbsentry_sz);
409 _(KDGKBTYPE, WRITE, 1);
410 _(KDMAPDISP, NONE, 0);
411 _(KDMKTONE, NONE, 0);
412 _(KDSETKEYCODE, READ, struct_kbkeycode_sz);
413 _(KDSETLED, NONE, 0);
414 _(KDSETMODE, NONE, 0);
415 _(KDSIGACCEPT, NONE, 0);
416 _(KDSKBDIACR, READ, struct_kbdiacrs_sz);
417 _(KDSKBENT, READ, struct_kbentry_sz);
418 _(KDSKBLED, NONE, 0);
419 _(KDSKBMETA, NONE, 0);
420 _(KDSKBMODE, NONE, 0);
421 _(KDSKBSENT, READ, struct_kbsentry_sz);
422 _(KDUNMAPDISP, NONE, 0);
423 _(KIOCSOUND, NONE, 0);
424 _(LPABORT, NONE, 0);
425 _(LPABORTOPEN, NONE, 0);
426 _(LPCAREFUL, NONE, 0);
427 _(LPCHAR, NONE, 0);
428 _(LPGETIRQ, WRITE, sizeof(int));
429 _(LPGETSTATUS, WRITE, sizeof(int));
430 _(LPRESET, NONE, 0);
431 _(LPSETIRQ, NONE, 0);
432 _(LPTIME, NONE, 0);
433 _(LPWAIT, NONE, 0);
434 _(MTIOCGETCONFIG, WRITE, struct_mtconfiginfo_sz);
435 _(MTIOCSETCONFIG, READ, struct_mtconfiginfo_sz);
436 _(PIO_CMAP, NONE, 0);
437 _(PIO_FONT, READ, 8192);
438 _(PIO_SCRNMAP, READ, e_tabsz);
439 _(PIO_UNIMAP, READ, struct_unimapdesc_sz);
440 _(PIO_UNIMAPCLR, READ, struct_unimapinit_sz);
441 _(PIO_UNISCRNMAP, READ, sizeof(short) * e_tabsz);
442 _(SCSI_IOCTL_PROBE_HOST, READ, sizeof(int));
443 _(SCSI_IOCTL_TAGGED_DISABLE, NONE, 0);
444 _(SCSI_IOCTL_TAGGED_ENABLE, NONE, 0);
445 _(SNDCTL_DSP_GETISPACE, WRITE, struct_audio_buf_info_sz);
446 _(SNDCTL_DSP_GETOSPACE, WRITE, struct_audio_buf_info_sz);
447 _(TIOCGSERIAL, WRITE, struct_serial_struct_sz);
448 _(TIOCSERGETMULTI, WRITE, struct_serial_multiport_struct_sz);
449 _(TIOCSERSETMULTI, READ, struct_serial_multiport_struct_sz);
450 _(TIOCSSERIAL, READ, struct_serial_struct_sz);
451
452 // The following ioctl requests are shared between AX25, IPX, netrom and
453 // mrouted.
454 // _(SIOCAIPXITFCRT, READ, sizeof(char));
455 // _(SIOCAX25GETUID, READ, struct_sockaddr_ax25_sz);
456 // _(SIOCNRGETPARMS, WRITE, struct_nr_parms_struct_sz);
457 // _(SIOCAIPXPRISLT, READ, sizeof(char));
458 // _(SIOCNRSETPARMS, READ, struct_nr_parms_struct_sz);
459 // _(SIOCAX25ADDUID, READ, struct_sockaddr_ax25_sz);
460 // _(SIOCNRDECOBS, NONE, 0);
461 // _(SIOCAX25DELUID, READ, struct_sockaddr_ax25_sz);
462 // _(SIOCIPXCFGDATA, WRITE, struct_ipx_config_data_sz);
463 // _(SIOCAX25NOUID, READ, sizeof(int));
464 // _(SIOCNRRTCTL, READ, sizeof(int));
465 // _(SIOCAX25DIGCTL, READ, sizeof(int));
466 // _(SIOCAX25GETPARMS, WRITE, struct_ax25_parms_struct_sz);
467 // _(SIOCAX25SETPARMS, READ, struct_ax25_parms_struct_sz);
468#endif
469#undef _
470}
471
472static bool ioctl_initialized = false;
473
474struct ioctl_desc_compare {
475 bool operator()(const ioctl_desc& left, const ioctl_desc& right) const {
476 return left.req < right.req;
477 }
478};
479
480static void ioctl_init() {
481 ioctl_table_fill();
482 Sort(ioctl_table, ioctl_table_size, ioctl_desc_compare());
483
484 bool bad = false;
485 for (unsigned i = 0; i < ioctl_table_size - 1; ++i) {
486 if (ioctl_table[i].req >= ioctl_table[i + 1].req) {
487 Printf("Duplicate or unsorted ioctl request id %x >= %x (%s vs %s)\n",
488 ioctl_table[i].req, ioctl_table[i + 1].req, ioctl_table[i].name,
489 ioctl_table[i + 1].name);
490 bad = true;
491 }
492 }
493
494 if (bad) Die();
495
496 ioctl_initialized = true;
497}
498
499// Handle the most evil ioctls that encode argument value as part of request id.
500static unsigned ioctl_request_fixup(unsigned req) {
501#if SANITIZER_LINUX
502 // Strip size and event number.
503 const unsigned kEviocgbitMask =
504 (IOC_SIZEMASK << IOC_SIZESHIFT) | EVIOC_EV_MAX;
505 if ((req & ~kEviocgbitMask) == IOCTL_EVIOCGBIT)
506 return IOCTL_EVIOCGBIT;
507 // Strip absolute axis number.
508 if ((req & ~EVIOC_ABS_MAX) == IOCTL_EVIOCGABS)
509 return IOCTL_EVIOCGABS;
510 if ((req & ~EVIOC_ABS_MAX) == IOCTL_EVIOCSABS)
511 return IOCTL_EVIOCSABS;
512#endif
513 return req;
514}
515
516static const ioctl_desc *ioctl_table_lookup(unsigned req) {
517 int left = 0;
518 int right = ioctl_table_size;
519 while (left < right) {
520 int mid = (left + right) / 2;
521 if (ioctl_table[mid].req < req)
522 left = mid + 1;
523 else
524 right = mid;
525 }
526 if (left == right && ioctl_table[left].req == req)
527 return ioctl_table + left;
528 else
529 return nullptr;
530}
531
532static bool ioctl_decode(unsigned req, ioctl_desc *desc) {
533 CHECK(desc);
534 desc->req = req;
535 desc->name = "<DECODED_IOCTL>";
536 desc->size = IOC_SIZE(req);
537 // Sanity check.
538 if (desc->size > 0xFFFF) return false;
539 unsigned dir = IOC_DIR(req);
540 switch (dir) {
541 case IOC_NONE:
542 desc->type = ioctl_desc::NONE;
543 break;
544 case IOC_READ | IOC_WRITE:
545 desc->type = ioctl_desc::READWRITE;
546 break;
547 case IOC_READ:
548 desc->type = ioctl_desc::WRITE;
549 break;
550 case IOC_WRITE:
551 desc->type = ioctl_desc::READ;
552 break;
553 default:
554 return false;
555 }
556 // Size can be 0 iff type is NONE.
557 if ((desc->type == IOC_NONE) != (desc->size == 0)) return false;
558 // Sanity check.
559 if (IOC_TYPE(req) == 0) return false;
560 return true;
561}
562
563static const ioctl_desc *ioctl_lookup(unsigned req) {
564 req = ioctl_request_fixup(req);
565 const ioctl_desc *desc = ioctl_table_lookup(req);
566 if (desc) return desc;
567
568 // Try stripping access size from the request id.
569 desc = ioctl_table_lookup(req & ~(IOC_SIZEMASK << IOC_SIZESHIFT));
570 // Sanity check: requests that encode access size are either read or write and
571 // have size of 0 in the table.
572 if (desc && desc->size == 0 &&
573 (desc->type == ioctl_desc::READWRITE || desc->type == ioctl_desc::WRITE ||
574 desc->type == ioctl_desc::READ))
575 return desc;
576 return nullptr;
577}
578
579static void ioctl_common_pre(void *ctx, const ioctl_desc *desc, int d,
580 unsigned request, void *arg) {
581 if (desc->type == ioctl_desc::READ || desc->type == ioctl_desc::READWRITE) {
582 unsigned size = desc->size ? desc->size : IOC_SIZE(request);
583 COMMON_INTERCEPTOR_READ_RANGE(ctx, arg, size);
584 }
585 if (desc->type != ioctl_desc::CUSTOM)
586 return;
587 if (request == IOCTL_SIOCGIFCONF) {
588 struct __sanitizer_ifconf *ifc = (__sanitizer_ifconf *)arg;
589 COMMON_INTERCEPTOR_READ_RANGE(ctx, (char*)&ifc->ifc_len,
590 sizeof(ifc->ifc_len));
591 }
592}
593
594static void ioctl_common_post(void *ctx, const ioctl_desc *desc, int res, int d,
595 unsigned request, void *arg) {
596 if (desc->type == ioctl_desc::WRITE || desc->type == ioctl_desc::READWRITE) {
597 // FIXME: add verbose output
598 unsigned size = desc->size ? desc->size : IOC_SIZE(request);
599 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, arg, size);
600 }
601 if (desc->type != ioctl_desc::CUSTOM)
602 return;
603 if (request == IOCTL_SIOCGIFCONF) {
604 struct __sanitizer_ifconf *ifc = (__sanitizer_ifconf *)arg;
605 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifc->ifc_ifcu.ifcu_req, ifc->ifc_len);
606 }
607}
608
609#endif
lib/tsan/sanitizer_common/sanitizer_common_interceptors_netbsd_compat.inc created+128
...@@ -0,0 +1,128 @@
1//===-- sanitizer_common_interceptors_netbsd_compat.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// Common function interceptors for tools like AddressSanitizer,
10// ThreadSanitizer, MemorySanitizer, etc.
11//
12// Interceptors for NetBSD old function calls that have been versioned.
13//
14// NetBSD minimal version supported 9.0.
15// NetBSD current version supported 9.99.26.
16//
17//===----------------------------------------------------------------------===//
18
19#if SANITIZER_NETBSD
20
21// First undef all mangled symbols.
22// Next, define compat interceptors.
23// Finally, undef INIT_ and redefine it.
24// This allows to avoid preprocessor issues.
25
26#undef fstatvfs
27#undef fstatvfs1
28#undef getmntinfo
29#undef getvfsstat
30#undef statvfs
31#undef statvfs1
32
33INTERCEPTOR(int, statvfs, char *path, void *buf) {
34 void *ctx;
35 COMMON_INTERCEPTOR_ENTER(ctx, statvfs, path, buf);
36 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
37 // FIXME: under ASan the call below may write to freed memory and corrupt
38 // its metadata. See
39 // https://github.com/google/sanitizers/issues/321.
40 int res = REAL(statvfs)(path, buf);
41 if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs90_sz);
42 return res;
43}
44
45INTERCEPTOR(int, fstatvfs, int fd, void *buf) {
46 void *ctx;
47 COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs, fd, buf);
48 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
49 // FIXME: under ASan the call below may write to freed memory and corrupt
50 // its metadata. See
51 // https://github.com/google/sanitizers/issues/321.
52 int res = REAL(fstatvfs)(fd, buf);
53 if (!res) {
54 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs90_sz);
55 if (fd >= 0)
56 COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
57 }
58 return res;
59}
60
61#undef INIT_STATVFS
62#define INIT_STATVFS \
63 COMMON_INTERCEPT_FUNCTION(statvfs); \
64 COMMON_INTERCEPT_FUNCTION(fstatvfs); \
65 COMMON_INTERCEPT_FUNCTION(__statvfs90); \
66 COMMON_INTERCEPT_FUNCTION(__fstatvfs90)
67
68INTERCEPTOR(int, __getmntinfo13, void **mntbufp, int flags) {
69 void *ctx;
70 COMMON_INTERCEPTOR_ENTER(ctx, __getmntinfo13, mntbufp, flags);
71 int cnt = REAL(__getmntinfo13)(mntbufp, flags);
72 if (cnt > 0 && mntbufp) {
73 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mntbufp, sizeof(void *));
74 if (*mntbufp)
75 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *mntbufp, cnt * struct_statvfs90_sz);
76 }
77 return cnt;
78}
79
80#undef INIT_GETMNTINFO
81#define INIT_GETMNTINFO \
82 COMMON_INTERCEPT_FUNCTION(__getmntinfo13); \
83 COMMON_INTERCEPT_FUNCTION(__getmntinfo90)
84
85INTERCEPTOR(int, getvfsstat, void *buf, SIZE_T bufsize, int flags) {
86 void *ctx;
87 COMMON_INTERCEPTOR_ENTER(ctx, getvfsstat, buf, bufsize, flags);
88 int ret = REAL(getvfsstat)(buf, bufsize, flags);
89 if (buf && ret > 0)
90 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, ret * struct_statvfs90_sz);
91 return ret;
92}
93
94#undef INIT_GETVFSSTAT
95#define INIT_GETVFSSTAT \
96 COMMON_INTERCEPT_FUNCTION(getvfsstat); \
97 COMMON_INTERCEPT_FUNCTION(__getvfsstat90)
98
99INTERCEPTOR(int, statvfs1, const char *path, void *buf, int flags) {
100 void *ctx;
101 COMMON_INTERCEPTOR_ENTER(ctx, statvfs1, path, buf, flags);
102 if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
103 int res = REAL(statvfs1)(path, buf, flags);
104 if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs90_sz);
105 return res;
106}
107
108INTERCEPTOR(int, fstatvfs1, int fd, void *buf, int flags) {
109 void *ctx;
110 COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs1, fd, buf, flags);
111 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
112 int res = REAL(fstatvfs1)(fd, buf, flags);
113 if (!res) {
114 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs90_sz);
115 if (fd >= 0)
116 COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
117 }
118 return res;
119}
120
121#undef INIT_STATVFS1
122#define INIT_STATVFS1 \
123 COMMON_INTERCEPT_FUNCTION(statvfs1); \
124 COMMON_INTERCEPT_FUNCTION(fstatvfs1); \
125 COMMON_INTERCEPT_FUNCTION(__statvfs190); \
126 COMMON_INTERCEPT_FUNCTION(__fstatvfs190)
127
128#endif
lib/tsan/sanitizer_common/sanitizer_common_interface.inc created+41
...@@ -0,0 +1,41 @@
1//===-- sanitizer_common_interface.inc ------------------------------------===//
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// Sanitizer Common interface list.
9//===----------------------------------------------------------------------===//
10INTERFACE_FUNCTION(__sanitizer_acquire_crash_state)
11INTERFACE_FUNCTION(__sanitizer_annotate_contiguous_container)
12INTERFACE_FUNCTION(__sanitizer_contiguous_container_find_bad_address)
13INTERFACE_FUNCTION(__sanitizer_set_death_callback)
14INTERFACE_FUNCTION(__sanitizer_set_report_path)
15INTERFACE_FUNCTION(__sanitizer_set_report_fd)
16INTERFACE_FUNCTION(__sanitizer_verify_contiguous_container)
17INTERFACE_WEAK_FUNCTION(__sanitizer_on_print)
18INTERFACE_WEAK_FUNCTION(__sanitizer_report_error_summary)
19INTERFACE_WEAK_FUNCTION(__sanitizer_sandbox_on_notify)
20// Sanitizer weak hooks
21INTERFACE_WEAK_FUNCTION(__sanitizer_weak_hook_memcmp)
22INTERFACE_WEAK_FUNCTION(__sanitizer_weak_hook_strcmp)
23INTERFACE_WEAK_FUNCTION(__sanitizer_weak_hook_strncmp)
24INTERFACE_WEAK_FUNCTION(__sanitizer_weak_hook_strstr)
25// Stacktrace interface.
26INTERFACE_FUNCTION(__sanitizer_get_module_and_offset_for_pc)
27INTERFACE_FUNCTION(__sanitizer_symbolize_global)
28INTERFACE_FUNCTION(__sanitizer_symbolize_pc)
29// Allocator interface.
30INTERFACE_FUNCTION(__sanitizer_get_allocated_size)
31INTERFACE_FUNCTION(__sanitizer_get_current_allocated_bytes)
32INTERFACE_FUNCTION(__sanitizer_get_estimated_allocated_size)
33INTERFACE_FUNCTION(__sanitizer_get_free_bytes)
34INTERFACE_FUNCTION(__sanitizer_get_heap_size)
35INTERFACE_FUNCTION(__sanitizer_get_ownership)
36INTERFACE_FUNCTION(__sanitizer_get_unmapped_bytes)
37INTERFACE_FUNCTION(__sanitizer_install_malloc_and_free_hooks)
38INTERFACE_FUNCTION(__sanitizer_purge_allocator)
39INTERFACE_FUNCTION(__sanitizer_print_memory_profile)
40INTERFACE_WEAK_FUNCTION(__sanitizer_free_hook)
41INTERFACE_WEAK_FUNCTION(__sanitizer_malloc_hook)
lib/tsan/sanitizer_common/sanitizer_common_interface_posix.inc created+13
...@@ -0,0 +1,13 @@
1//===-- sanitizer_common_interface_posix.inc ------------------------------===//
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// Sanitizer Common interface list only available for Posix systems.
9//===----------------------------------------------------------------------===//
10INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_code)
11INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_data)
12INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_demangle)
13INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_flush)
lib/tsan/sanitizer_common/sanitizer_common_syscalls.inc created+2914
...@@ -0,0 +1,2914 @@
1//===-- sanitizer_common_syscalls.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// Common syscalls handlers for tools like AddressSanitizer,
10// ThreadSanitizer, MemorySanitizer, etc.
11//
12// This file should be included into the tool's interceptor file,
13// which has to define it's own macros:
14// COMMON_SYSCALL_PRE_READ_RANGE
15// Called in prehook for regions that will be read by the kernel and
16// must be initialized.
17// COMMON_SYSCALL_PRE_WRITE_RANGE
18// Called in prehook for regions that will be written to by the kernel
19// and must be addressable. The actual write range may be smaller than
20// reported in the prehook. See POST_WRITE_RANGE.
21// COMMON_SYSCALL_POST_READ_RANGE
22// Called in posthook for regions that were read by the kernel. Does
23// not make much sense.
24// COMMON_SYSCALL_POST_WRITE_RANGE
25// Called in posthook for regions that were written to by the kernel
26// and are now initialized.
27// COMMON_SYSCALL_ACQUIRE(addr)
28// Acquire memory visibility from addr.
29// COMMON_SYSCALL_RELEASE(addr)
30// Release memory visibility to addr.
31// COMMON_SYSCALL_FD_CLOSE(fd)
32// Called before closing file descriptor fd.
33// COMMON_SYSCALL_FD_ACQUIRE(fd)
34// Acquire memory visibility from fd.
35// COMMON_SYSCALL_FD_RELEASE(fd)
36// Release memory visibility to fd.
37// COMMON_SYSCALL_PRE_FORK()
38// Called before fork syscall.
39// COMMON_SYSCALL_POST_FORK(long res)
40// Called after fork syscall.
41//===----------------------------------------------------------------------===//
42
43#include "sanitizer_platform.h"
44#if SANITIZER_LINUX
45
46#include "sanitizer_libc.h"
47
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)
52
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)
57
58#ifndef COMMON_SYSCALL_ACQUIRE
59# define COMMON_SYSCALL_ACQUIRE(addr) ((void)(addr))
60#endif
61
62#ifndef COMMON_SYSCALL_RELEASE
63# define COMMON_SYSCALL_RELEASE(addr) ((void)(addr))
64#endif
65
66#ifndef COMMON_SYSCALL_FD_CLOSE
67# define COMMON_SYSCALL_FD_CLOSE(fd) ((void)(fd))
68#endif
69
70#ifndef COMMON_SYSCALL_FD_ACQUIRE
71# define COMMON_SYSCALL_FD_ACQUIRE(fd) ((void)(fd))
72#endif
73
74#ifndef COMMON_SYSCALL_FD_RELEASE
75# define COMMON_SYSCALL_FD_RELEASE(fd) ((void)(fd))
76#endif
77
78#ifndef COMMON_SYSCALL_PRE_FORK
79# define COMMON_SYSCALL_PRE_FORK() {}
80#endif
81
82#ifndef COMMON_SYSCALL_POST_FORK
83# define COMMON_SYSCALL_POST_FORK(res) {}
84#endif
85
86// FIXME: do some kind of PRE_READ for all syscall arguments (int(s) and such).
87
88extern "C" {
89struct sanitizer_kernel_iovec {
90 void *iov_base;
91 unsigned long iov_len;
92};
93
94struct sanitizer_kernel_msghdr {
95 void *msg_name;
96 int msg_namelen;
97 struct sanitizer_kernel_iovec *msg_iov;
98 unsigned long msg_iovlen;
99 void *msg_control;
100 unsigned long msg_controllen;
101 unsigned msg_flags;
102};
103
104struct sanitizer_kernel_mmsghdr {
105 struct sanitizer_kernel_msghdr msg_hdr;
106 unsigned msg_len;
107};
108
109struct sanitizer_kernel_timespec {
110 long tv_sec;
111 long tv_nsec;
112};
113
114struct sanitizer_kernel_timeval {
115 long tv_sec;
116 long tv_usec;
117};
118
119struct sanitizer_kernel_rusage {
120 struct sanitizer_kernel_timeval ru_timeval[2];
121 long ru_long[14];
122};
123
124struct sanitizer_kernel_sockaddr {
125 unsigned short sa_family;
126 char sa_data[14];
127};
128
129// Real sigset size is always passed as a syscall argument.
130// Declare it "void" to catch sizeof(kernel_sigset_t).
131typedef void kernel_sigset_t;
132
133static void kernel_write_iovec(const __sanitizer_iovec *iovec,
134 SIZE_T iovlen, SIZE_T maxlen) {
135 for (SIZE_T i = 0; i < iovlen && maxlen; ++i) {
136 SSIZE_T sz = Min(iovec[i].iov_len, maxlen);
137 POST_WRITE(iovec[i].iov_base, sz);
138 maxlen -= sz;
139 }
140}
141
142// This functions uses POST_READ, because it needs to run after syscall to know
143// the real read range.
144static void kernel_read_iovec(const __sanitizer_iovec *iovec,
145 SIZE_T iovlen, SIZE_T maxlen) {
146 POST_READ(iovec, sizeof(*iovec) * iovlen);
147 for (SIZE_T i = 0; i < iovlen && maxlen; ++i) {
148 SSIZE_T sz = Min(iovec[i].iov_len, maxlen);
149 POST_READ(iovec[i].iov_base, sz);
150 maxlen -= sz;
151 }
152}
153
154PRE_SYSCALL(recvmsg)(long sockfd, sanitizer_kernel_msghdr *msg, long flags) {
155 PRE_READ(msg, sizeof(*msg));
156}
157
158POST_SYSCALL(recvmsg)(long res, long sockfd, sanitizer_kernel_msghdr *msg,
159 long flags) {
160 if (res >= 0) {
161 if (msg) {
162 for (unsigned long i = 0; i < msg->msg_iovlen; ++i) {
163 POST_WRITE(msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len);
164 }
165 POST_WRITE(msg->msg_control, msg->msg_controllen);
166 }
167 }
168}
169
170PRE_SYSCALL(recvmmsg)(long fd, sanitizer_kernel_mmsghdr *msg, long vlen,
171 long flags, void *timeout) {
172 PRE_READ(msg, vlen * sizeof(*msg));
173}
174
175POST_SYSCALL(recvmmsg)(long res, long fd, sanitizer_kernel_mmsghdr *msg,
176 long vlen, long flags, void *timeout) {
177 if (res >= 0) {
178 if (msg) {
179 for (unsigned long i = 0; i < msg->msg_hdr.msg_iovlen; ++i) {
180 POST_WRITE(msg->msg_hdr.msg_iov[i].iov_base,
181 msg->msg_hdr.msg_iov[i].iov_len);
182 }
183 POST_WRITE(msg->msg_hdr.msg_control, msg->msg_hdr.msg_controllen);
184 POST_WRITE(&msg->msg_len, sizeof(msg->msg_len));
185 }
186 if (timeout) POST_WRITE(timeout, struct_timespec_sz);
187 }
188}
189
190PRE_SYSCALL(read)(long fd, void *buf, uptr count) {
191 if (buf) {
192 PRE_WRITE(buf, count);
193 }
194}
195
196POST_SYSCALL(read)(long res, long fd, void *buf, uptr count) {
197 if (res > 0 && buf) {
198 POST_WRITE(buf, res);
199 }
200}
201
202PRE_SYSCALL(time)(void *tloc) {}
203
204POST_SYSCALL(time)(long res, void *tloc) {
205 if (res >= 0) {
206 if (tloc) POST_WRITE(tloc, sizeof(long));
207 }
208}
209
210PRE_SYSCALL(stime)(void *tptr) {}
211
212POST_SYSCALL(stime)(long res, void *tptr) {
213 if (res >= 0) {
214 if (tptr) POST_WRITE(tptr, sizeof(long));
215 }
216}
217
218PRE_SYSCALL(gettimeofday)(void *tv, void *tz) {}
219
220POST_SYSCALL(gettimeofday)(long res, void *tv, void *tz) {
221 if (res >= 0) {
222 if (tv) POST_WRITE(tv, timeval_sz);
223 if (tz) POST_WRITE(tz, struct_timezone_sz);
224 }
225}
226
227PRE_SYSCALL(settimeofday)(void *tv, void *tz) {}
228
229POST_SYSCALL(settimeofday)(long res, void *tv, void *tz) {
230 if (res >= 0) {
231 if (tv) POST_WRITE(tv, timeval_sz);
232 if (tz) POST_WRITE(tz, struct_timezone_sz);
233 }
234}
235
236#if !SANITIZER_ANDROID
237PRE_SYSCALL(adjtimex)(void *txc_p) {}
238
239POST_SYSCALL(adjtimex)(long res, void *txc_p) {
240 if (res >= 0) {
241 if (txc_p) POST_WRITE(txc_p, struct_timex_sz);
242 }
243}
244#endif
245
246PRE_SYSCALL(times)(void *tbuf) {}
247
248POST_SYSCALL(times)(long res, void *tbuf) {
249 if (res >= 0) {
250 if (tbuf) POST_WRITE(tbuf, struct_tms_sz);
251 }
252}
253
254PRE_SYSCALL(gettid)() {}
255
256POST_SYSCALL(gettid)(long res) {}
257
258PRE_SYSCALL(nanosleep)(void *rqtp, void *rmtp) {}
259
260POST_SYSCALL(nanosleep)(long res, void *rqtp, void *rmtp) {
261 if (res >= 0) {
262 if (rqtp) POST_WRITE(rqtp, struct_timespec_sz);
263 if (rmtp) POST_WRITE(rmtp, struct_timespec_sz);
264 }
265}
266
267PRE_SYSCALL(alarm)(long seconds) {}
268
269POST_SYSCALL(alarm)(long res, long seconds) {}
270
271PRE_SYSCALL(getpid)() {}
272
273POST_SYSCALL(getpid)(long res) {}
274
275PRE_SYSCALL(getppid)() {}
276
277POST_SYSCALL(getppid)(long res) {}
278
279PRE_SYSCALL(getuid)() {}
280
281POST_SYSCALL(getuid)(long res) {}
282
283PRE_SYSCALL(geteuid)() {}
284
285POST_SYSCALL(geteuid)(long res) {}
286
287PRE_SYSCALL(getgid)() {}
288
289POST_SYSCALL(getgid)(long res) {}
290
291PRE_SYSCALL(getegid)() {}
292
293POST_SYSCALL(getegid)(long res) {}
294
295PRE_SYSCALL(getresuid)(void *ruid, void *euid, void *suid) {}
296
297POST_SYSCALL(getresuid)(long res, void *ruid, void *euid, void *suid) {
298 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));
302 }
303}
304
305PRE_SYSCALL(getresgid)(void *rgid, void *egid, void *sgid) {}
306
307POST_SYSCALL(getresgid)(long res, void *rgid, void *egid, void *sgid) {
308 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));
312 }
313}
314
315PRE_SYSCALL(getpgid)(long pid) {}
316
317POST_SYSCALL(getpgid)(long res, long pid) {}
318
319PRE_SYSCALL(getpgrp)() {}
320
321POST_SYSCALL(getpgrp)(long res) {}
322
323PRE_SYSCALL(getsid)(long pid) {}
324
325POST_SYSCALL(getsid)(long res, long pid) {}
326
327PRE_SYSCALL(getgroups)(long gidsetsize, void *grouplist) {}
328
329POST_SYSCALL(getgroups)(long res, long gidsetsize,
330 __sanitizer___kernel_gid_t *grouplist) {
331 if (res >= 0) {
332 if (grouplist) POST_WRITE(grouplist, res * sizeof(*grouplist));
333 }
334}
335
336PRE_SYSCALL(setregid)(long rgid, long egid) {}
337
338POST_SYSCALL(setregid)(long res, long rgid, long egid) {}
339
340PRE_SYSCALL(setgid)(long gid) {}
341
342POST_SYSCALL(setgid)(long res, long gid) {}
343
344PRE_SYSCALL(setreuid)(long ruid, long euid) {}
345
346POST_SYSCALL(setreuid)(long res, long ruid, long euid) {}
347
348PRE_SYSCALL(setuid)(long uid) {}
349
350POST_SYSCALL(setuid)(long res, long uid) {}
351
352PRE_SYSCALL(setresuid)(long ruid, long euid, long suid) {}
353
354POST_SYSCALL(setresuid)(long res, long ruid, long euid, long suid) {}
355
356PRE_SYSCALL(setresgid)(long rgid, long egid, long sgid) {}
357
358POST_SYSCALL(setresgid)(long res, long rgid, long egid, long sgid) {}
359
360PRE_SYSCALL(setfsuid)(long uid) {}
361
362POST_SYSCALL(setfsuid)(long res, long uid) {}
363
364PRE_SYSCALL(setfsgid)(long gid) {}
365
366POST_SYSCALL(setfsgid)(long res, long gid) {}
367
368PRE_SYSCALL(setpgid)(long pid, long pgid) {}
369
370POST_SYSCALL(setpgid)(long res, long pid, long pgid) {}
371
372PRE_SYSCALL(setsid)() {}
373
374POST_SYSCALL(setsid)(long res) {}
375
376PRE_SYSCALL(setgroups)(long gidsetsize, __sanitizer___kernel_gid_t *grouplist) {
377 if (grouplist) POST_WRITE(grouplist, gidsetsize * sizeof(*grouplist));
378}
379
380POST_SYSCALL(setgroups)(long res, long gidsetsize,
381 __sanitizer___kernel_gid_t *grouplist) {}
382
383PRE_SYSCALL(acct)(const void *name) {
384 if (name)
385 PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
386}
387
388POST_SYSCALL(acct)(long res, const void *name) {}
389
390PRE_SYSCALL(capget)(void *header, void *dataptr) {
391 if (header) PRE_READ(header, __user_cap_header_struct_sz);
392}
393
394POST_SYSCALL(capget)(long res, void *header, void *dataptr) {
395 if (res >= 0)
396 if (dataptr) POST_WRITE(dataptr, __user_cap_data_struct_sz);
397}
398
399PRE_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);
402}
403
404POST_SYSCALL(capset)(long res, void *header, const void *data) {}
405
406PRE_SYSCALL(personality)(long personality) {}
407
408POST_SYSCALL(personality)(long res, long personality) {}
409
410PRE_SYSCALL(sigpending)(void *set) {}
411
412POST_SYSCALL(sigpending)(long res, void *set) {
413 if (res >= 0) {
414 if (set) POST_WRITE(set, old_sigset_t_sz);
415 }
416}
417
418PRE_SYSCALL(sigprocmask)(long how, void *set, void *oset) {}
419
420POST_SYSCALL(sigprocmask)(long res, long how, void *set, void *oset) {
421 if (res >= 0) {
422 if (set) POST_WRITE(set, old_sigset_t_sz);
423 if (oset) POST_WRITE(oset, old_sigset_t_sz);
424 }
425}
426
427PRE_SYSCALL(getitimer)(long which, void *value) {}
428
429POST_SYSCALL(getitimer)(long res, long which, void *value) {
430 if (res >= 0) {
431 if (value) POST_WRITE(value, struct_itimerval_sz);
432 }
433}
434
435PRE_SYSCALL(setitimer)(long which, void *value, void *ovalue) {}
436
437POST_SYSCALL(setitimer)(long res, long which, void *value, void *ovalue) {
438 if (res >= 0) {
439 if (value) POST_WRITE(value, struct_itimerval_sz);
440 if (ovalue) POST_WRITE(ovalue, struct_itimerval_sz);
441 }
442}
443
444PRE_SYSCALL(timer_create)(long which_clock, void *timer_event_spec,
445 void *created_timer_id) {}
446
447POST_SYSCALL(timer_create)(long res, long which_clock, void *timer_event_spec,
448 void *created_timer_id) {
449 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));
452 }
453}
454
455PRE_SYSCALL(timer_gettime)(long timer_id, void *setting) {}
456
457POST_SYSCALL(timer_gettime)(long res, long timer_id, void *setting) {
458 if (res >= 0) {
459 if (setting) POST_WRITE(setting, struct_itimerspec_sz);
460 }
461}
462
463PRE_SYSCALL(timer_getoverrun)(long timer_id) {}
464
465POST_SYSCALL(timer_getoverrun)(long res, long timer_id) {}
466
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);
470}
471
472POST_SYSCALL(timer_settime)(long res, long timer_id, long flags,
473 const void *new_setting, void *old_setting) {
474 if (res >= 0) {
475 if (old_setting) POST_WRITE(old_setting, struct_itimerspec_sz);
476 }
477}
478
479PRE_SYSCALL(timer_delete)(long timer_id) {}
480
481POST_SYSCALL(timer_delete)(long res, long timer_id) {}
482
483PRE_SYSCALL(clock_settime)(long which_clock, const void *tp) {
484 if (tp) PRE_READ(tp, struct_timespec_sz);
485}
486
487POST_SYSCALL(clock_settime)(long res, long which_clock, const void *tp) {}
488
489PRE_SYSCALL(clock_gettime)(long which_clock, void *tp) {}
490
491POST_SYSCALL(clock_gettime)(long res, long which_clock, void *tp) {
492 if (res >= 0) {
493 if (tp) POST_WRITE(tp, struct_timespec_sz);
494 }
495}
496
497#if !SANITIZER_ANDROID
498PRE_SYSCALL(clock_adjtime)(long which_clock, void *tx) {}
499
500POST_SYSCALL(clock_adjtime)(long res, long which_clock, void *tx) {
501 if (res >= 0) {
502 if (tx) POST_WRITE(tx, struct_timex_sz);
503 }
504}
505#endif
506
507PRE_SYSCALL(clock_getres)(long which_clock, void *tp) {}
508
509POST_SYSCALL(clock_getres)(long res, long which_clock, void *tp) {
510 if (res >= 0) {
511 if (tp) POST_WRITE(tp, struct_timespec_sz);
512 }
513}
514
515PRE_SYSCALL(clock_nanosleep)(long which_clock, long flags, const void *rqtp,
516 void *rmtp) {
517 if (rqtp) PRE_READ(rqtp, struct_timespec_sz);
518}
519
520POST_SYSCALL(clock_nanosleep)(long res, long which_clock, long flags,
521 const void *rqtp, void *rmtp) {
522 if (res >= 0) {
523 if (rmtp) POST_WRITE(rmtp, struct_timespec_sz);
524 }
525}
526
527PRE_SYSCALL(nice)(long increment) {}
528
529POST_SYSCALL(nice)(long res, long increment) {}
530
531PRE_SYSCALL(sched_setscheduler)(long pid, long policy, void *param) {}
532
533POST_SYSCALL(sched_setscheduler)(long res, long pid, long policy, void *param) {
534 if (res >= 0) {
535 if (param) POST_WRITE(param, struct_sched_param_sz);
536 }
537}
538
539PRE_SYSCALL(sched_setparam)(long pid, void *param) {
540 if (param) PRE_READ(param, struct_sched_param_sz);
541}
542
543POST_SYSCALL(sched_setparam)(long res, long pid, void *param) {}
544
545PRE_SYSCALL(sched_getscheduler)(long pid) {}
546
547POST_SYSCALL(sched_getscheduler)(long res, long pid) {}
548
549PRE_SYSCALL(sched_getparam)(long pid, void *param) {}
550
551POST_SYSCALL(sched_getparam)(long res, long pid, void *param) {
552 if (res >= 0) {
553 if (param) POST_WRITE(param, struct_sched_param_sz);
554 }
555}
556
557PRE_SYSCALL(sched_setaffinity)(long pid, long len, void *user_mask_ptr) {
558 if (user_mask_ptr) PRE_READ(user_mask_ptr, len);
559}
560
561POST_SYSCALL(sched_setaffinity)(long res, long pid, long len,
562 void *user_mask_ptr) {}
563
564PRE_SYSCALL(sched_getaffinity)(long pid, long len, void *user_mask_ptr) {}
565
566POST_SYSCALL(sched_getaffinity)(long res, long pid, long len,
567 void *user_mask_ptr) {
568 if (res >= 0) {
569 if (user_mask_ptr) POST_WRITE(user_mask_ptr, len);
570 }
571}
572
573PRE_SYSCALL(sched_yield)() {}
574
575POST_SYSCALL(sched_yield)(long res) {}
576
577PRE_SYSCALL(sched_get_priority_max)(long policy) {}
578
579POST_SYSCALL(sched_get_priority_max)(long res, long policy) {}
580
581PRE_SYSCALL(sched_get_priority_min)(long policy) {}
582
583POST_SYSCALL(sched_get_priority_min)(long res, long policy) {}
584
585PRE_SYSCALL(sched_rr_get_interval)(long pid, void *interval) {}
586
587POST_SYSCALL(sched_rr_get_interval)(long res, long pid, void *interval) {
588 if (res >= 0) {
589 if (interval) POST_WRITE(interval, struct_timespec_sz);
590 }
591}
592
593PRE_SYSCALL(setpriority)(long which, long who, long niceval) {}
594
595POST_SYSCALL(setpriority)(long res, long which, long who, long niceval) {}
596
597PRE_SYSCALL(getpriority)(long which, long who) {}
598
599POST_SYSCALL(getpriority)(long res, long which, long who) {}
600
601PRE_SYSCALL(shutdown)(long arg0, long arg1) {}
602
603POST_SYSCALL(shutdown)(long res, long arg0, long arg1) {}
604
605PRE_SYSCALL(reboot)(long magic1, long magic2, long cmd, void *arg) {}
606
607POST_SYSCALL(reboot)(long res, long magic1, long magic2, long cmd, void *arg) {}
608
609PRE_SYSCALL(restart_syscall)() {}
610
611POST_SYSCALL(restart_syscall)(long res) {}
612
613PRE_SYSCALL(kexec_load)(long entry, long nr_segments, void *segments,
614 long flags) {}
615
616POST_SYSCALL(kexec_load)(long res, long entry, long nr_segments, void *segments,
617 long flags) {
618 if (res >= 0) {
619 if (segments) POST_WRITE(segments, struct_kexec_segment_sz);
620 }
621}
622
623PRE_SYSCALL(exit)(long error_code) {}
624
625POST_SYSCALL(exit)(long res, long error_code) {}
626
627PRE_SYSCALL(exit_group)(long error_code) {}
628
629POST_SYSCALL(exit_group)(long res, long error_code) {}
630
631PRE_SYSCALL(wait4)(long pid, void *stat_addr, long options, void *ru) {}
632
633POST_SYSCALL(wait4)(long res, long pid, void *stat_addr, long options,
634 void *ru) {
635 if (res >= 0) {
636 if (stat_addr) POST_WRITE(stat_addr, sizeof(int));
637 if (ru) POST_WRITE(ru, struct_rusage_sz);
638 }
639}
640
641PRE_SYSCALL(waitid)(long which, long pid, void *infop, long options, void *ru) {
642}
643
644POST_SYSCALL(waitid)(long res, long which, long pid, void *infop, long options,
645 void *ru) {
646 if (res >= 0) {
647 if (infop) POST_WRITE(infop, siginfo_t_sz);
648 if (ru) POST_WRITE(ru, struct_rusage_sz);
649 }
650}
651
652PRE_SYSCALL(waitpid)(long pid, void *stat_addr, long options) {}
653
654POST_SYSCALL(waitpid)(long res, long pid, void *stat_addr, long options) {
655 if (res >= 0) {
656 if (stat_addr) POST_WRITE(stat_addr, sizeof(int));
657 }
658}
659
660PRE_SYSCALL(set_tid_address)(void *tidptr) {}
661
662POST_SYSCALL(set_tid_address)(long res, void *tidptr) {
663 if (res >= 0) {
664 if (tidptr) POST_WRITE(tidptr, sizeof(int));
665 }
666}
667
668PRE_SYSCALL(init_module)(void *umod, long len, const void *uargs) {
669 if (uargs)
670 PRE_READ(uargs, __sanitizer::internal_strlen((const char *)uargs) + 1);
671}
672
673POST_SYSCALL(init_module)(long res, void *umod, long len, const void *uargs) {}
674
675PRE_SYSCALL(delete_module)(const void *name_user, long flags) {
676 if (name_user)
677 PRE_READ(name_user,
678 __sanitizer::internal_strlen((const char *)name_user) + 1);
679}
680
681POST_SYSCALL(delete_module)(long res, const void *name_user, long flags) {}
682
683PRE_SYSCALL(rt_sigprocmask)(long how, void *set, void *oset, long sigsetsize) {}
684
685POST_SYSCALL(rt_sigprocmask)(long res, long how, kernel_sigset_t *set,
686 kernel_sigset_t *oset, long sigsetsize) {
687 if (res >= 0) {
688 if (set) POST_WRITE(set, sigsetsize);
689 if (oset) POST_WRITE(oset, sigsetsize);
690 }
691}
692
693PRE_SYSCALL(rt_sigpending)(void *set, long sigsetsize) {}
694
695POST_SYSCALL(rt_sigpending)(long res, kernel_sigset_t *set, long sigsetsize) {
696 if (res >= 0) {
697 if (set) POST_WRITE(set, sigsetsize);
698 }
699}
700
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);
705}
706
707POST_SYSCALL(rt_sigtimedwait)(long res, const void *uthese, void *uinfo,
708 const void *uts, long sigsetsize) {
709 if (res >= 0) {
710 if (uinfo) POST_WRITE(uinfo, siginfo_t_sz);
711 }
712}
713
714PRE_SYSCALL(rt_tgsigqueueinfo)(long tgid, long pid, long sig, void *uinfo) {}
715
716POST_SYSCALL(rt_tgsigqueueinfo)(long res, long tgid, long pid, long sig,
717 void *uinfo) {
718 if (res >= 0) {
719 if (uinfo) POST_WRITE(uinfo, siginfo_t_sz);
720 }
721}
722
723PRE_SYSCALL(kill)(long pid, long sig) {}
724
725POST_SYSCALL(kill)(long res, long pid, long sig) {}
726
727PRE_SYSCALL(tgkill)(long tgid, long pid, long sig) {}
728
729POST_SYSCALL(tgkill)(long res, long tgid, long pid, long sig) {}
730
731PRE_SYSCALL(tkill)(long pid, long sig) {}
732
733POST_SYSCALL(tkill)(long res, long pid, long sig) {}
734
735PRE_SYSCALL(rt_sigqueueinfo)(long pid, long sig, void *uinfo) {}
736
737POST_SYSCALL(rt_sigqueueinfo)(long res, long pid, long sig, void *uinfo) {
738 if (res >= 0) {
739 if (uinfo) POST_WRITE(uinfo, siginfo_t_sz);
740 }
741}
742
743PRE_SYSCALL(sgetmask)() {}
744
745POST_SYSCALL(sgetmask)(long res) {}
746
747PRE_SYSCALL(ssetmask)(long newmask) {}
748
749POST_SYSCALL(ssetmask)(long res, long newmask) {}
750
751PRE_SYSCALL(signal)(long sig, long handler) {}
752
753POST_SYSCALL(signal)(long res, long sig, long handler) {}
754
755PRE_SYSCALL(pause)() {}
756
757POST_SYSCALL(pause)(long res) {}
758
759PRE_SYSCALL(sync)() {}
760
761POST_SYSCALL(sync)(long res) {}
762
763PRE_SYSCALL(fsync)(long fd) {}
764
765POST_SYSCALL(fsync)(long res, long fd) {}
766
767PRE_SYSCALL(fdatasync)(long fd) {}
768
769POST_SYSCALL(fdatasync)(long res, long fd) {}
770
771PRE_SYSCALL(bdflush)(long func, long data) {}
772
773POST_SYSCALL(bdflush)(long res, long func, long data) {}
774
775PRE_SYSCALL(mount)(void *dev_name, void *dir_name, void *type, long flags,
776 void *data) {}
777
778POST_SYSCALL(mount)(long res, void *dev_name, void *dir_name, void *type,
779 long flags, void *data) {
780 if (res >= 0) {
781 if (dev_name)
782 POST_WRITE(dev_name,
783 __sanitizer::internal_strlen((const char *)dev_name) + 1);
784 if (dir_name)
785 POST_WRITE(dir_name,
786 __sanitizer::internal_strlen((const char *)dir_name) + 1);
787 if (type)
788 POST_WRITE(type, __sanitizer::internal_strlen((const char *)type) + 1);
789 }
790}
791
792PRE_SYSCALL(umount)(void *name, long flags) {}
793
794POST_SYSCALL(umount)(long res, void *name, long flags) {
795 if (res >= 0) {
796 if (name)
797 POST_WRITE(name, __sanitizer::internal_strlen((const char *)name) + 1);
798 }
799}
800
801PRE_SYSCALL(oldumount)(void *name) {}
802
803POST_SYSCALL(oldumount)(long res, void *name) {
804 if (res >= 0) {
805 if (name)
806 POST_WRITE(name, __sanitizer::internal_strlen((const char *)name) + 1);
807 }
808}
809
810PRE_SYSCALL(truncate)(const void *path, long length) {
811 if (path)
812 PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
813}
814
815POST_SYSCALL(truncate)(long res, const void *path, long length) {}
816
817PRE_SYSCALL(ftruncate)(long fd, long length) {}
818
819POST_SYSCALL(ftruncate)(long res, long fd, long length) {}
820
821PRE_SYSCALL(stat)(const void *filename, void *statbuf) {
822 if (filename)
823 PRE_READ(filename,
824 __sanitizer::internal_strlen((const char *)filename) + 1);
825}
826
827POST_SYSCALL(stat)(long res, const void *filename, void *statbuf) {
828 if (res >= 0) {
829 if (statbuf) POST_WRITE(statbuf, struct___old_kernel_stat_sz);
830 }
831}
832
833#if !SANITIZER_ANDROID
834PRE_SYSCALL(statfs)(const void *path, void *buf) {
835 if (path)
836 PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
837}
838
839POST_SYSCALL(statfs)(long res, const void *path, void *buf) {
840 if (res >= 0) {
841 if (buf) POST_WRITE(buf, struct_statfs_sz);
842 }
843}
844
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}
849
850POST_SYSCALL(statfs64)(long res, const void *path, long sz, void *buf) {
851 if (res >= 0) {
852 if (buf) POST_WRITE(buf, struct_statfs64_sz);
853 }
854}
855
856PRE_SYSCALL(fstatfs)(long fd, void *buf) {}
857
858POST_SYSCALL(fstatfs)(long res, long fd, void *buf) {
859 if (res >= 0) {
860 if (buf) POST_WRITE(buf, struct_statfs_sz);
861 }
862}
863
864PRE_SYSCALL(fstatfs64)(long fd, long sz, void *buf) {}
865
866POST_SYSCALL(fstatfs64)(long res, long fd, long sz, void *buf) {
867 if (res >= 0) {
868 if (buf) POST_WRITE(buf, struct_statfs64_sz);
869 }
870}
871#endif // !SANITIZER_ANDROID
872
873PRE_SYSCALL(lstat)(const void *filename, void *statbuf) {
874 if (filename)
875 PRE_READ(filename,
876 __sanitizer::internal_strlen((const char *)filename) + 1);
877}
878
879POST_SYSCALL(lstat)(long res, const void *filename, void *statbuf) {
880 if (res >= 0) {
881 if (statbuf) POST_WRITE(statbuf, struct___old_kernel_stat_sz);
882 }
883}
884
885PRE_SYSCALL(fstat)(long fd, void *statbuf) {}
886
887POST_SYSCALL(fstat)(long res, long fd, void *statbuf) {
888 if (res >= 0) {
889 if (statbuf) POST_WRITE(statbuf, struct___old_kernel_stat_sz);
890 }
891}
892
893PRE_SYSCALL(newstat)(const void *filename, void *statbuf) {
894 if (filename)
895 PRE_READ(filename,
896 __sanitizer::internal_strlen((const char *)filename) + 1);
897}
898
899POST_SYSCALL(newstat)(long res, const void *filename, void *statbuf) {
900 if (res >= 0) {
901 if (statbuf) POST_WRITE(statbuf, struct_kernel_stat_sz);
902 }
903}
904
905PRE_SYSCALL(newlstat)(const void *filename, void *statbuf) {
906 if (filename)
907 PRE_READ(filename,
908 __sanitizer::internal_strlen((const char *)filename) + 1);
909}
910
911POST_SYSCALL(newlstat)(long res, const void *filename, void *statbuf) {
912 if (res >= 0) {
913 if (statbuf) POST_WRITE(statbuf, struct_kernel_stat_sz);
914 }
915}
916
917PRE_SYSCALL(newfstat)(long fd, void *statbuf) {}
918
919POST_SYSCALL(newfstat)(long res, long fd, void *statbuf) {
920 if (res >= 0) {
921 if (statbuf) POST_WRITE(statbuf, struct_kernel_stat_sz);
922 }
923}
924
925#if !SANITIZER_ANDROID
926PRE_SYSCALL(ustat)(long dev, void *ubuf) {}
927
928POST_SYSCALL(ustat)(long res, long dev, void *ubuf) {
929 if (res >= 0) {
930 if (ubuf) POST_WRITE(ubuf, struct_ustat_sz);
931 }
932}
933#endif // !SANITIZER_ANDROID
934
935PRE_SYSCALL(stat64)(const void *filename, void *statbuf) {
936 if (filename)
937 PRE_READ(filename,
938 __sanitizer::internal_strlen((const char *)filename) + 1);
939}
940
941POST_SYSCALL(stat64)(long res, const void *filename, void *statbuf) {
942 if (res >= 0) {
943 if (statbuf) POST_WRITE(statbuf, struct_kernel_stat64_sz);
944 }
945}
946
947PRE_SYSCALL(fstat64)(long fd, void *statbuf) {}
948
949POST_SYSCALL(fstat64)(long res, long fd, void *statbuf) {
950 if (res >= 0) {
951 if (statbuf) POST_WRITE(statbuf, struct_kernel_stat64_sz);
952 }
953}
954
955PRE_SYSCALL(lstat64)(const void *filename, void *statbuf) {
956 if (filename)
957 PRE_READ(filename,
958 __sanitizer::internal_strlen((const char *)filename) + 1);
959}
960
961POST_SYSCALL(lstat64)(long res, const void *filename, void *statbuf) {
962 if (res >= 0) {
963 if (statbuf) POST_WRITE(statbuf, struct_kernel_stat64_sz);
964 }
965}
966
967PRE_SYSCALL(setxattr)(const void *path, const void *name, const void *value,
968 long size, long flags) {
969 if (path)
970 PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
971 if (name)
972 PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
973 if (value) PRE_READ(value, size);
974}
975
976POST_SYSCALL(setxattr)(long res, const void *path, const void *name,
977 const void *value, long size, long flags) {}
978
979PRE_SYSCALL(lsetxattr)(const void *path, const void *name, const void *value,
980 long size, long flags) {
981 if (path)
982 PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
983 if (name)
984 PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
985 if (value) PRE_READ(value, size);
986}
987
988POST_SYSCALL(lsetxattr)(long res, const void *path, const void *name,
989 const void *value, long size, long flags) {}
990
991PRE_SYSCALL(fsetxattr)(long fd, const void *name, const void *value, long size,
992 long flags) {
993 if (name)
994 PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
995 if (value) PRE_READ(value, size);
996}
997
998POST_SYSCALL(fsetxattr)(long res, long fd, const void *name, const void *value,
999 long size, long flags) {}
1000
1001PRE_SYSCALL(getxattr)(const void *path, const void *name, void *value,
1002 long size) {
1003 if (path)
1004 PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
1005 if (name)
1006 PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
1007}
1008
1009POST_SYSCALL(getxattr)(long res, const void *path, const void *name,
1010 void *value, long size) {
1011 if (size && res > 0) {
1012 if (value) POST_WRITE(value, res);
1013 }
1014}
1015
1016PRE_SYSCALL(lgetxattr)(const void *path, const void *name, void *value,
1017 long size) {
1018 if (path)
1019 PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
1020 if (name)
1021 PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
1022}
1023
1024POST_SYSCALL(lgetxattr)(long res, const void *path, const void *name,
1025 void *value, long size) {
1026 if (size && res > 0) {
1027 if (value) POST_WRITE(value, res);
1028 }
1029}
1030
1031PRE_SYSCALL(fgetxattr)(long fd, const void *name, void *value, long size) {
1032 if (name)
1033 PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
1034}
1035
1036POST_SYSCALL(fgetxattr)(long res, long fd, const void *name, void *value,
1037 long size) {
1038 if (size && res > 0) {
1039 if (value) POST_WRITE(value, res);
1040 }
1041}
1042
1043PRE_SYSCALL(listxattr)(const void *path, void *list, long size) {
1044 if (path)
1045 PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
1046}
1047
1048POST_SYSCALL(listxattr)(long res, const void *path, void *list, long size) {
1049 if (size && res > 0) {
1050 if (list) POST_WRITE(list, res);
1051 }
1052}
1053
1054PRE_SYSCALL(llistxattr)(const void *path, void *list, long size) {
1055 if (path)
1056 PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
1057}
1058
1059POST_SYSCALL(llistxattr)(long res, const void *path, void *list, long size) {
1060 if (size && res > 0) {
1061 if (list) POST_WRITE(list, res);
1062 }
1063}
1064
1065PRE_SYSCALL(flistxattr)(long fd, void *list, long size) {}
1066
1067POST_SYSCALL(flistxattr)(long res, long fd, void *list, long size) {
1068 if (size && res > 0) {
1069 if (list) POST_WRITE(list, res);
1070 }
1071}
1072
1073PRE_SYSCALL(removexattr)(const void *path, const void *name) {
1074 if (path)
1075 PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
1076 if (name)
1077 PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
1078}
1079
1080POST_SYSCALL(removexattr)(long res, const void *path, const void *name) {}
1081
1082PRE_SYSCALL(lremovexattr)(const void *path, const void *name) {
1083 if (path)
1084 PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
1085 if (name)
1086 PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
1087}
1088
1089POST_SYSCALL(lremovexattr)(long res, const void *path, const void *name) {}
1090
1091PRE_SYSCALL(fremovexattr)(long fd, const void *name) {
1092 if (name)
1093 PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
1094}
1095
1096POST_SYSCALL(fremovexattr)(long res, long fd, const void *name) {}
1097
1098PRE_SYSCALL(brk)(long brk) {}
1099
1100POST_SYSCALL(brk)(long res, long brk) {}
1101
1102PRE_SYSCALL(mprotect)(long start, long len, long prot) {}
1103
1104POST_SYSCALL(mprotect)(long res, long start, long len, long prot) {}
1105
1106PRE_SYSCALL(mremap)(long addr, long old_len, long new_len, long flags,
1107 long new_addr) {}
1108
1109POST_SYSCALL(mremap)(long res, long addr, long old_len, long new_len,
1110 long flags, long new_addr) {}
1111
1112PRE_SYSCALL(remap_file_pages)(long start, long size, long prot, long pgoff,
1113 long flags) {}
1114
1115POST_SYSCALL(remap_file_pages)(long res, long start, long size, long prot,
1116 long pgoff, long flags) {}
1117
1118PRE_SYSCALL(msync)(long start, long len, long flags) {}
1119
1120POST_SYSCALL(msync)(long res, long start, long len, long flags) {}
1121
1122PRE_SYSCALL(munmap)(long addr, long len) {}
1123
1124POST_SYSCALL(munmap)(long res, long addr, long len) {}
1125
1126PRE_SYSCALL(mlock)(long start, long len) {}
1127
1128POST_SYSCALL(mlock)(long res, long start, long len) {}
1129
1130PRE_SYSCALL(munlock)(long start, long len) {}
1131
1132POST_SYSCALL(munlock)(long res, long start, long len) {}
1133
1134PRE_SYSCALL(mlockall)(long flags) {}
1135
1136POST_SYSCALL(mlockall)(long res, long flags) {}
1137
1138PRE_SYSCALL(munlockall)() {}
1139
1140POST_SYSCALL(munlockall)(long res) {}
1141
1142PRE_SYSCALL(madvise)(long start, long len, long behavior) {}
1143
1144POST_SYSCALL(madvise)(long res, long start, long len, long behavior) {}
1145
1146PRE_SYSCALL(mincore)(long start, long len, void *vec) {}
1147
1148POST_SYSCALL(mincore)(long res, long start, long len, void *vec) {
1149 if (res >= 0) {
1150 if (vec) {
1151 POST_WRITE(vec, (len + GetPageSizeCached() - 1) / GetPageSizeCached());
1152 }
1153 }
1154}
1155
1156PRE_SYSCALL(pivot_root)(const void *new_root, const void *put_old) {
1157 if (new_root)
1158 PRE_READ(new_root,
1159 __sanitizer::internal_strlen((const char *)new_root) + 1);
1160 if (put_old)
1161 PRE_READ(put_old, __sanitizer::internal_strlen((const char *)put_old) + 1);
1162}
1163
1164POST_SYSCALL(pivot_root)(long res, const void *new_root, const void *put_old) {}
1165
1166PRE_SYSCALL(chroot)(const void *filename) {
1167 if (filename)
1168 PRE_READ(filename,
1169 __sanitizer::internal_strlen((const char *)filename) + 1);
1170}
1171
1172POST_SYSCALL(chroot)(long res, const void *filename) {}
1173
1174PRE_SYSCALL(mknod)(const void *filename, long mode, long dev) {
1175 if (filename)
1176 PRE_READ(filename,
1177 __sanitizer::internal_strlen((const char *)filename) + 1);
1178}
1179
1180POST_SYSCALL(mknod)(long res, const void *filename, long mode, long dev) {}
1181
1182PRE_SYSCALL(link)(const void *oldname, const void *newname) {
1183 if (oldname)
1184 PRE_READ(oldname, __sanitizer::internal_strlen((const char *)oldname) + 1);
1185 if (newname)
1186 PRE_READ(newname, __sanitizer::internal_strlen((const char *)newname) + 1);
1187}
1188
1189POST_SYSCALL(link)(long res, const void *oldname, const void *newname) {}
1190
1191PRE_SYSCALL(symlink)(const void *old, const void *new_) {
1192 if (old) PRE_READ(old, __sanitizer::internal_strlen((const char *)old) + 1);
1193 if (new_)
1194 PRE_READ(new_, __sanitizer::internal_strlen((const char *)new_) + 1);
1195}
1196
1197POST_SYSCALL(symlink)(long res, const void *old, const void *new_) {}
1198
1199PRE_SYSCALL(unlink)(const void *pathname) {
1200 if (pathname)
1201 PRE_READ(pathname,
1202 __sanitizer::internal_strlen((const char *)pathname) + 1);
1203}
1204
1205POST_SYSCALL(unlink)(long res, const void *pathname) {}
1206
1207PRE_SYSCALL(rename)(const void *oldname, const void *newname) {
1208 if (oldname)
1209 PRE_READ(oldname, __sanitizer::internal_strlen((const char *)oldname) + 1);
1210 if (newname)
1211 PRE_READ(newname, __sanitizer::internal_strlen((const char *)newname) + 1);
1212}
1213
1214POST_SYSCALL(rename)(long res, const void *oldname, const void *newname) {}
1215
1216PRE_SYSCALL(chmod)(const void *filename, long mode) {
1217 if (filename)
1218 PRE_READ(filename,
1219 __sanitizer::internal_strlen((const char *)filename) + 1);
1220}
1221
1222POST_SYSCALL(chmod)(long res, const void *filename, long mode) {}
1223
1224PRE_SYSCALL(fchmod)(long fd, long mode) {}
1225
1226POST_SYSCALL(fchmod)(long res, long fd, long mode) {}
1227
1228PRE_SYSCALL(fcntl)(long fd, long cmd, long arg) {}
1229
1230POST_SYSCALL(fcntl)(long res, long fd, long cmd, long arg) {}
1231
1232PRE_SYSCALL(fcntl64)(long fd, long cmd, long arg) {}
1233
1234POST_SYSCALL(fcntl64)(long res, long fd, long cmd, long arg) {}
1235
1236PRE_SYSCALL(pipe)(void *fildes) {}
1237
1238POST_SYSCALL(pipe)(long res, void *fildes) {
1239 if (res >= 0)
1240 if (fildes) POST_WRITE(fildes, sizeof(int) * 2);
1241}
1242
1243PRE_SYSCALL(pipe2)(void *fildes, long flags) {}
1244
1245POST_SYSCALL(pipe2)(long res, void *fildes, long flags) {
1246 if (res >= 0)
1247 if (fildes) POST_WRITE(fildes, sizeof(int) * 2);
1248}
1249
1250PRE_SYSCALL(dup)(long fildes) {}
1251
1252POST_SYSCALL(dup)(long res, long fildes) {}
1253
1254PRE_SYSCALL(dup2)(long oldfd, long newfd) {}
1255
1256POST_SYSCALL(dup2)(long res, long oldfd, long newfd) {}
1257
1258PRE_SYSCALL(dup3)(long oldfd, long newfd, long flags) {}
1259
1260POST_SYSCALL(dup3)(long res, long oldfd, long newfd, long flags) {}
1261
1262PRE_SYSCALL(ioperm)(long from, long num, long on) {}
1263
1264POST_SYSCALL(ioperm)(long res, long from, long num, long on) {}
1265
1266PRE_SYSCALL(ioctl)(long fd, long cmd, long arg) {}
1267
1268POST_SYSCALL(ioctl)(long res, long fd, long cmd, long arg) {}
1269
1270PRE_SYSCALL(flock)(long fd, long cmd) {}
1271
1272POST_SYSCALL(flock)(long res, long fd, long cmd) {}
1273
1274PRE_SYSCALL(io_setup)(long nr_reqs, void **ctx) {
1275 if (ctx) PRE_WRITE(ctx, sizeof(*ctx));
1276}
1277
1278POST_SYSCALL(io_setup)(long res, long nr_reqs, void **ctx) {
1279 if (res >= 0) {
1280 if (ctx) POST_WRITE(ctx, sizeof(*ctx));
1281 // (*ctx) is actually a pointer to a kernel mapped page, and there are
1282 // people out there who are crazy enough to peek into that page's 32-byte
1283 // header.
1284 if (*ctx) POST_WRITE(*ctx, 32);
1285 }
1286}
1287
1288PRE_SYSCALL(io_destroy)(long ctx) {}
1289
1290POST_SYSCALL(io_destroy)(long res, long ctx) {}
1291
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);
1295}
1296
1297POST_SYSCALL(io_getevents)(long res, long ctx_id, long min_nr, long nr,
1298 __sanitizer_io_event *ioevpp, void *timeout) {
1299 if (res >= 0) {
1300 if (ioevpp) POST_WRITE(ioevpp, res * sizeof(*ioevpp));
1301 if (timeout) POST_WRITE(timeout, struct_timespec_sz);
1302 }
1303 for (long i = 0; i < res; i++) {
1304 // We synchronize io_submit -> io_getevents/io_cancel using the
1305 // user-provided data context. Data is not necessary a pointer, it can be
1306 // an int, 0 or whatever; acquire/release will correctly handle this.
1307 // This scheme can lead to false negatives, e.g. when all operations
1308 // synchronize on 0. But there does not seem to be a better solution
1309 // (except wrapping all operations in own context, which is unreliable).
1310 // We can not reliably extract fildes in io_getevents.
1311 COMMON_SYSCALL_ACQUIRE((void*)ioevpp[i].data);
1312 }
1313}
1314
1315PRE_SYSCALL(io_submit)(long ctx_id, long nr, __sanitizer_iocb **iocbpp) {
1316 for (long i = 0; i < nr; ++i) {
1317 uptr op = iocbpp[i]->aio_lio_opcode;
1318 void *data = (void*)iocbpp[i]->aio_data;
1319 void *buf = (void*)iocbpp[i]->aio_buf;
1320 uptr len = (uptr)iocbpp[i]->aio_nbytes;
1321 if (op == iocb_cmd_pwrite && buf && len) {
1322 PRE_READ(buf, len);
1323 } else if (op == iocb_cmd_pread && buf && len) {
1324 POST_WRITE(buf, len);
1325 } else if (op == iocb_cmd_pwritev) {
1326 __sanitizer_iovec *iovec = (__sanitizer_iovec*)buf;
1327 for (uptr v = 0; v < len; v++)
1328 PRE_READ(iovec[v].iov_base, iovec[v].iov_len);
1329 } else if (op == iocb_cmd_preadv) {
1330 __sanitizer_iovec *iovec = (__sanitizer_iovec*)buf;
1331 for (uptr v = 0; v < len; v++)
1332 POST_WRITE(iovec[v].iov_base, iovec[v].iov_len);
1333 }
1334 // See comment in io_getevents.
1335 COMMON_SYSCALL_RELEASE(data);
1336 }
1337}
1338
1339POST_SYSCALL(io_submit)(long res, long ctx_id, long nr,
1340 __sanitizer_iocb **iocbpp) {}
1341
1342PRE_SYSCALL(io_cancel)(long ctx_id, __sanitizer_iocb *iocb,
1343 __sanitizer_io_event *result) {
1344}
1345
1346POST_SYSCALL(io_cancel)(long res, long ctx_id, __sanitizer_iocb *iocb,
1347 __sanitizer_io_event *result) {
1348 if (res == 0) {
1349 if (result) {
1350 // See comment in io_getevents.
1351 COMMON_SYSCALL_ACQUIRE((void*)result->data);
1352 POST_WRITE(result, sizeof(*result));
1353 }
1354 if (iocb)
1355 POST_WRITE(iocb, sizeof(*iocb));
1356 }
1357}
1358
1359PRE_SYSCALL(sendfile)(long out_fd, long in_fd, void *offset, long count) {}
1360
1361POST_SYSCALL(sendfile)(long res, long out_fd, long in_fd,
1362 __sanitizer___kernel_off_t *offset, long count) {
1363 if (res >= 0) {
1364 if (offset) POST_WRITE(offset, sizeof(*offset));
1365 }
1366}
1367
1368PRE_SYSCALL(sendfile64)(long out_fd, long in_fd, void *offset, long count) {}
1369
1370POST_SYSCALL(sendfile64)(long res, long out_fd, long in_fd,
1371 __sanitizer___kernel_loff_t *offset, long count) {
1372 if (res >= 0) {
1373 if (offset) POST_WRITE(offset, sizeof(*offset));
1374 }
1375}
1376
1377PRE_SYSCALL(readlink)(const void *path, void *buf, long bufsiz) {
1378 if (path)
1379 PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
1380}
1381
1382POST_SYSCALL(readlink)(long res, const void *path, void *buf, long bufsiz) {
1383 if (res >= 0) {
1384 if (buf)
1385 POST_WRITE(buf, __sanitizer::internal_strlen((const char *)buf) + 1);
1386 }
1387}
1388
1389PRE_SYSCALL(creat)(const void *pathname, long mode) {
1390 if (pathname)
1391 PRE_READ(pathname,
1392 __sanitizer::internal_strlen((const char *)pathname) + 1);
1393}
1394
1395POST_SYSCALL(creat)(long res, const void *pathname, long mode) {}
1396
1397PRE_SYSCALL(open)(const void *filename, long flags, long mode) {
1398 if (filename)
1399 PRE_READ(filename,
1400 __sanitizer::internal_strlen((const char *)filename) + 1);
1401}
1402
1403POST_SYSCALL(open)(long res, const void *filename, long flags, long mode) {}
1404
1405PRE_SYSCALL(close)(long fd) {
1406 COMMON_SYSCALL_FD_CLOSE((int)fd);
1407}
1408
1409POST_SYSCALL(close)(long res, long fd) {}
1410
1411PRE_SYSCALL(access)(const void *filename, long mode) {
1412 if (filename)
1413 PRE_READ(filename,
1414 __sanitizer::internal_strlen((const char *)filename) + 1);
1415}
1416
1417POST_SYSCALL(access)(long res, const void *filename, long mode) {}
1418
1419PRE_SYSCALL(vhangup)() {}
1420
1421POST_SYSCALL(vhangup)(long res) {}
1422
1423PRE_SYSCALL(chown)(const void *filename, long user, long group) {
1424 if (filename)
1425 PRE_READ(filename,
1426 __sanitizer::internal_strlen((const char *)filename) + 1);
1427}
1428
1429POST_SYSCALL(chown)(long res, const void *filename, long user, long group) {}
1430
1431PRE_SYSCALL(lchown)(const void *filename, long user, long group) {
1432 if (filename)
1433 PRE_READ(filename,
1434 __sanitizer::internal_strlen((const char *)filename) + 1);
1435}
1436
1437POST_SYSCALL(lchown)(long res, const void *filename, long user, long group) {}
1438
1439PRE_SYSCALL(fchown)(long fd, long user, long group) {}
1440
1441POST_SYSCALL(fchown)(long res, long fd, long user, long group) {}
1442
1443#if SANITIZER_USES_UID16_SYSCALLS
1444PRE_SYSCALL(chown16)(const void *filename, long user, long group) {
1445 if (filename)
1446 PRE_READ(filename,
1447 __sanitizer::internal_strlen((const char *)filename) + 1);
1448}
1449
1450POST_SYSCALL(chown16)(long res, const void *filename, long user, long group) {}
1451
1452PRE_SYSCALL(lchown16)(const void *filename, long user, long group) {
1453 if (filename)
1454 PRE_READ(filename,
1455 __sanitizer::internal_strlen((const char *)filename) + 1);
1456}
1457
1458POST_SYSCALL(lchown16)(long res, const void *filename, long user, long group) {}
1459
1460PRE_SYSCALL(fchown16)(long fd, long user, long group) {}
1461
1462POST_SYSCALL(fchown16)(long res, long fd, long user, long group) {}
1463
1464PRE_SYSCALL(setregid16)(long rgid, long egid) {}
1465
1466POST_SYSCALL(setregid16)(long res, long rgid, long egid) {}
1467
1468PRE_SYSCALL(setgid16)(long gid) {}
1469
1470POST_SYSCALL(setgid16)(long res, long gid) {}
1471
1472PRE_SYSCALL(setreuid16)(long ruid, long euid) {}
1473
1474POST_SYSCALL(setreuid16)(long res, long ruid, long euid) {}
1475
1476PRE_SYSCALL(setuid16)(long uid) {}
1477
1478POST_SYSCALL(setuid16)(long res, long uid) {}
1479
1480PRE_SYSCALL(setresuid16)(long ruid, long euid, long suid) {}
1481
1482POST_SYSCALL(setresuid16)(long res, long ruid, long euid, long suid) {}
1483
1484PRE_SYSCALL(getresuid16)(void *ruid, void *euid, void *suid) {}
1485
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) {
1489 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));
1493 }
1494}
1495
1496PRE_SYSCALL(setresgid16)(long rgid, long egid, long sgid) {}
1497
1498POST_SYSCALL(setresgid16)(long res, long rgid, long egid, long sgid) {}
1499
1500PRE_SYSCALL(getresgid16)(void *rgid, void *egid, void *sgid) {}
1501
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) {
1505 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));
1509 }
1510}
1511
1512PRE_SYSCALL(setfsuid16)(long uid) {}
1513
1514POST_SYSCALL(setfsuid16)(long res, long uid) {}
1515
1516PRE_SYSCALL(setfsgid16)(long gid) {}
1517
1518POST_SYSCALL(setfsgid16)(long res, long gid) {}
1519
1520PRE_SYSCALL(getgroups16)(long gidsetsize,
1521 __sanitizer___kernel_old_gid_t *grouplist) {}
1522
1523POST_SYSCALL(getgroups16)(long res, long gidsetsize,
1524 __sanitizer___kernel_old_gid_t *grouplist) {
1525 if (res >= 0) {
1526 if (grouplist) POST_WRITE(grouplist, res * sizeof(*grouplist));
1527 }
1528}
1529
1530PRE_SYSCALL(setgroups16)(long gidsetsize,
1531 __sanitizer___kernel_old_gid_t *grouplist) {
1532 if (grouplist) POST_WRITE(grouplist, gidsetsize * sizeof(*grouplist));
1533}
1534
1535POST_SYSCALL(setgroups16)(long res, long gidsetsize,
1536 __sanitizer___kernel_old_gid_t *grouplist) {}
1537
1538PRE_SYSCALL(getuid16)() {}
1539
1540POST_SYSCALL(getuid16)(long res) {}
1541
1542PRE_SYSCALL(geteuid16)() {}
1543
1544POST_SYSCALL(geteuid16)(long res) {}
1545
1546PRE_SYSCALL(getgid16)() {}
1547
1548POST_SYSCALL(getgid16)(long res) {}
1549
1550PRE_SYSCALL(getegid16)() {}
1551
1552POST_SYSCALL(getegid16)(long res) {}
1553#endif // SANITIZER_USES_UID16_SYSCALLS
1554
1555PRE_SYSCALL(utime)(void *filename, void *times) {}
1556
1557POST_SYSCALL(utime)(long res, void *filename, void *times) {
1558 if (res >= 0) {
1559 if (filename)
1560 POST_WRITE(filename,
1561 __sanitizer::internal_strlen((const char *)filename) + 1);
1562 if (times) POST_WRITE(times, struct_utimbuf_sz);
1563 }
1564}
1565
1566PRE_SYSCALL(utimes)(void *filename, void *utimes) {}
1567
1568POST_SYSCALL(utimes)(long res, void *filename, void *utimes) {
1569 if (res >= 0) {
1570 if (filename)
1571 POST_WRITE(filename,
1572 __sanitizer::internal_strlen((const char *)filename) + 1);
1573 if (utimes) POST_WRITE(utimes, timeval_sz);
1574 }
1575}
1576
1577PRE_SYSCALL(lseek)(long fd, long offset, long origin) {}
1578
1579POST_SYSCALL(lseek)(long res, long fd, long offset, long origin) {}
1580
1581PRE_SYSCALL(llseek)(long fd, long offset_high, long offset_low, void *result,
1582 long origin) {}
1583
1584POST_SYSCALL(llseek)(long res, long fd, long offset_high, long offset_low,
1585 void *result, long origin) {
1586 if (res >= 0) {
1587 if (result) POST_WRITE(result, sizeof(long long));
1588 }
1589}
1590
1591PRE_SYSCALL(readv)(long fd, const __sanitizer_iovec *vec, long vlen) {}
1592
1593POST_SYSCALL(readv)(long res, long fd, const __sanitizer_iovec *vec,
1594 long vlen) {
1595 if (res >= 0) {
1596 if (vec) kernel_write_iovec(vec, vlen, res);
1597 }
1598}
1599
1600PRE_SYSCALL(write)(long fd, const void *buf, long count) {
1601 if (buf) PRE_READ(buf, count);
1602}
1603
1604POST_SYSCALL(write)(long res, long fd, const void *buf, long count) {}
1605
1606PRE_SYSCALL(writev)(long fd, const __sanitizer_iovec *vec, long vlen) {}
1607
1608POST_SYSCALL(writev)(long res, long fd, const __sanitizer_iovec *vec,
1609 long vlen) {
1610 if (res >= 0) {
1611 if (vec) kernel_read_iovec(vec, vlen, res);
1612 }
1613}
1614
1615#ifdef _LP64
1616PRE_SYSCALL(pread64)(long fd, void *buf, long count, long pos) {}
1617
1618POST_SYSCALL(pread64)(long res, long fd, void *buf, long count, long pos) {
1619 if (res >= 0) {
1620 if (buf) POST_WRITE(buf, res);
1621 }
1622}
1623
1624PRE_SYSCALL(pwrite64)(long fd, const void *buf, long count, long pos) {
1625 if (buf) PRE_READ(buf, count);
1626}
1627
1628POST_SYSCALL(pwrite64)(long res, long fd, const void *buf, long count,
1629 long pos) {}
1630#else
1631PRE_SYSCALL(pread64)(long fd, void *buf, long count, long pos0, long pos1) {}
1632
1633POST_SYSCALL(pread64)(long res, long fd, void *buf, long count, long pos0,
1634 long pos1) {
1635 if (res >= 0) {
1636 if (buf) POST_WRITE(buf, res);
1637 }
1638}
1639
1640PRE_SYSCALL(pwrite64)(long fd, const void *buf, long count, long pos0,
1641 long pos1) {
1642 if (buf) PRE_READ(buf, count);
1643}
1644
1645POST_SYSCALL(pwrite64)(long res, long fd, const void *buf, long count,
1646 long pos0, long pos1) {}
1647#endif
1648
1649PRE_SYSCALL(preadv)(long fd, const __sanitizer_iovec *vec, long vlen,
1650 long pos_l, long pos_h) {}
1651
1652POST_SYSCALL(preadv)(long res, long fd, const __sanitizer_iovec *vec, long vlen,
1653 long pos_l, long pos_h) {
1654 if (res >= 0) {
1655 if (vec) kernel_write_iovec(vec, vlen, res);
1656 }
1657}
1658
1659PRE_SYSCALL(pwritev)(long fd, const __sanitizer_iovec *vec, long vlen,
1660 long pos_l, long pos_h) {}
1661
1662POST_SYSCALL(pwritev)(long res, long fd, const __sanitizer_iovec *vec,
1663 long vlen, long pos_l, long pos_h) {
1664 if (res >= 0) {
1665 if (vec) kernel_read_iovec(vec, vlen, res);
1666 }
1667}
1668
1669PRE_SYSCALL(getcwd)(void *buf, long size) {}
1670
1671POST_SYSCALL(getcwd)(long res, void *buf, long size) {
1672 if (res >= 0) {
1673 if (buf)
1674 POST_WRITE(buf, __sanitizer::internal_strlen((const char *)buf) + 1);
1675 }
1676}
1677
1678PRE_SYSCALL(mkdir)(const void *pathname, long mode) {
1679 if (pathname)
1680 PRE_READ(pathname,
1681 __sanitizer::internal_strlen((const char *)pathname) + 1);
1682}
1683
1684POST_SYSCALL(mkdir)(long res, const void *pathname, long mode) {}
1685
1686PRE_SYSCALL(chdir)(const void *filename) {
1687 if (filename)
1688 PRE_READ(filename,
1689 __sanitizer::internal_strlen((const char *)filename) + 1);
1690}
1691
1692POST_SYSCALL(chdir)(long res, const void *filename) {}
1693
1694PRE_SYSCALL(fchdir)(long fd) {}
1695
1696POST_SYSCALL(fchdir)(long res, long fd) {}
1697
1698PRE_SYSCALL(rmdir)(const void *pathname) {
1699 if (pathname)
1700 PRE_READ(pathname,
1701 __sanitizer::internal_strlen((const char *)pathname) + 1);
1702}
1703
1704POST_SYSCALL(rmdir)(long res, const void *pathname) {}
1705
1706PRE_SYSCALL(lookup_dcookie)(u64 cookie64, void *buf, long len) {}
1707
1708POST_SYSCALL(lookup_dcookie)(long res, u64 cookie64, void *buf, long len) {
1709 if (res >= 0) {
1710 if (buf)
1711 POST_WRITE(buf, __sanitizer::internal_strlen((const char *)buf) + 1);
1712 }
1713}
1714
1715PRE_SYSCALL(quotactl)(long cmd, const void *special, long id, void *addr) {
1716 if (special)
1717 PRE_READ(special, __sanitizer::internal_strlen((const char *)special) + 1);
1718}
1719
1720POST_SYSCALL(quotactl)(long res, long cmd, const void *special, long id,
1721 void *addr) {}
1722
1723PRE_SYSCALL(getdents)(long fd, void *dirent, long count) {}
1724
1725POST_SYSCALL(getdents)(long res, long fd, void *dirent, long count) {
1726 if (res >= 0) {
1727 if (dirent) POST_WRITE(dirent, res);
1728 }
1729}
1730
1731PRE_SYSCALL(getdents64)(long fd, void *dirent, long count) {}
1732
1733POST_SYSCALL(getdents64)(long res, long fd, void *dirent, long count) {
1734 if (res >= 0) {
1735 if (dirent) POST_WRITE(dirent, res);
1736 }
1737}
1738
1739PRE_SYSCALL(setsockopt)(long fd, long level, long optname, void *optval,
1740 long optlen) {}
1741
1742POST_SYSCALL(setsockopt)(long res, long fd, long level, long optname,
1743 void *optval, long optlen) {
1744 if (res >= 0) {
1745 if (optval)
1746 POST_WRITE(optval,
1747 __sanitizer::internal_strlen((const char *)optval) + 1);
1748 }
1749}
1750
1751PRE_SYSCALL(getsockopt)(long fd, long level, long optname, void *optval,
1752 void *optlen) {}
1753
1754POST_SYSCALL(getsockopt)(long res, long fd, long level, long optname,
1755 void *optval, void *optlen) {
1756 if (res >= 0) {
1757 if (optval)
1758 POST_WRITE(optval,
1759 __sanitizer::internal_strlen((const char *)optval) + 1);
1760 if (optlen) POST_WRITE(optlen, sizeof(int));
1761 }
1762}
1763
1764PRE_SYSCALL(bind)(long arg0, sanitizer_kernel_sockaddr *arg1, long arg2) {}
1765
1766POST_SYSCALL(bind)(long res, long arg0, sanitizer_kernel_sockaddr *arg1,
1767 long arg2) {
1768 if (res >= 0) {
1769 if (arg1) POST_WRITE(arg1, sizeof(*arg1));
1770 }
1771}
1772
1773PRE_SYSCALL(connect)(long arg0, sanitizer_kernel_sockaddr *arg1, long arg2) {}
1774
1775POST_SYSCALL(connect)(long res, long arg0, sanitizer_kernel_sockaddr *arg1,
1776 long arg2) {
1777 if (res >= 0) {
1778 if (arg1) POST_WRITE(arg1, sizeof(*arg1));
1779 }
1780}
1781
1782PRE_SYSCALL(accept)(long arg0, sanitizer_kernel_sockaddr *arg1, void *arg2) {}
1783
1784POST_SYSCALL(accept)(long res, long arg0, sanitizer_kernel_sockaddr *arg1,
1785 void *arg2) {
1786 if (res >= 0) {
1787 if (arg1) POST_WRITE(arg1, sizeof(*arg1));
1788 if (arg2) POST_WRITE(arg2, sizeof(unsigned));
1789 }
1790}
1791
1792PRE_SYSCALL(accept4)(long arg0, sanitizer_kernel_sockaddr *arg1, void *arg2,
1793 long arg3) {}
1794
1795POST_SYSCALL(accept4)(long res, long arg0, sanitizer_kernel_sockaddr *arg1,
1796 void *arg2, long arg3) {
1797 if (res >= 0) {
1798 if (arg1) POST_WRITE(arg1, sizeof(*arg1));
1799 if (arg2) POST_WRITE(arg2, sizeof(unsigned));
1800 }
1801}
1802
1803PRE_SYSCALL(getsockname)(long arg0, sanitizer_kernel_sockaddr *arg1,
1804 void *arg2) {}
1805
1806POST_SYSCALL(getsockname)(long res, long arg0, sanitizer_kernel_sockaddr *arg1,
1807 void *arg2) {
1808 if (res >= 0) {
1809 if (arg1) POST_WRITE(arg1, sizeof(*arg1));
1810 if (arg2) POST_WRITE(arg2, sizeof(unsigned));
1811 }
1812}
1813
1814PRE_SYSCALL(getpeername)(long arg0, sanitizer_kernel_sockaddr *arg1,
1815 void *arg2) {}
1816
1817POST_SYSCALL(getpeername)(long res, long arg0, sanitizer_kernel_sockaddr *arg1,
1818 void *arg2) {
1819 if (res >= 0) {
1820 if (arg1) POST_WRITE(arg1, sizeof(*arg1));
1821 if (arg2) POST_WRITE(arg2, sizeof(unsigned));
1822 }
1823}
1824
1825PRE_SYSCALL(send)(long arg0, void *arg1, long arg2, long arg3) {}
1826
1827POST_SYSCALL(send)(long res, long arg0, void *arg1, long arg2, long arg3) {
1828 if (res) {
1829 if (arg1) POST_READ(arg1, res);
1830 }
1831}
1832
1833PRE_SYSCALL(sendto)(long arg0, void *arg1, long arg2, long arg3,
1834 sanitizer_kernel_sockaddr *arg4, long arg5) {}
1835
1836POST_SYSCALL(sendto)(long res, long arg0, void *arg1, long arg2, long arg3,
1837 sanitizer_kernel_sockaddr *arg4, long arg5) {
1838 if (res >= 0) {
1839 if (arg1) POST_READ(arg1, res);
1840 if (arg4) POST_WRITE(arg4, sizeof(*arg4));
1841 }
1842}
1843
1844PRE_SYSCALL(sendmsg)(long fd, void *msg, long flags) {}
1845
1846POST_SYSCALL(sendmsg)(long res, long fd, void *msg, long flags) {
1847 // FIXME: POST_READ
1848}
1849
1850PRE_SYSCALL(sendmmsg)(long fd, void *msg, long vlen, long flags) {}
1851
1852POST_SYSCALL(sendmmsg)(long res, long fd, void *msg, long vlen, long flags) {
1853 // FIXME: POST_READ
1854}
1855
1856PRE_SYSCALL(recv)(long arg0, void *buf, long len, long flags) {}
1857
1858POST_SYSCALL(recv)(long res, void *buf, long len, long flags) {
1859 if (res >= 0) {
1860 if (buf) POST_WRITE(buf, res);
1861 }
1862}
1863
1864PRE_SYSCALL(recvfrom)(long arg0, void *buf, long len, long flags,
1865 sanitizer_kernel_sockaddr *arg4, void *arg5) {}
1866
1867POST_SYSCALL(recvfrom)(long res, long arg0, void *buf, long len, long flags,
1868 sanitizer_kernel_sockaddr *arg4, void *arg5) {
1869 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));
1873 }
1874}
1875
1876PRE_SYSCALL(socket)(long arg0, long arg1, long arg2) {}
1877
1878POST_SYSCALL(socket)(long res, long arg0, long arg1, long arg2) {}
1879
1880PRE_SYSCALL(socketpair)(long arg0, long arg1, long arg2, int *sv) {}
1881
1882POST_SYSCALL(socketpair)(long res, long arg0, long arg1, long arg2, int *sv) {
1883 if (res >= 0)
1884 if (sv) POST_WRITE(sv, sizeof(int) * 2);
1885}
1886
1887PRE_SYSCALL(socketcall)(long call, void *args) {}
1888
1889POST_SYSCALL(socketcall)(long res, long call, void *args) {
1890 if (res >= 0) {
1891 if (args) POST_WRITE(args, sizeof(long));
1892 }
1893}
1894
1895PRE_SYSCALL(listen)(long arg0, long arg1) {}
1896
1897POST_SYSCALL(listen)(long res, long arg0, long arg1) {}
1898
1899PRE_SYSCALL(poll)(void *ufds, long nfds, long timeout) {}
1900
1901POST_SYSCALL(poll)(long res, __sanitizer_pollfd *ufds, long nfds,
1902 long timeout) {
1903 if (res >= 0) {
1904 if (ufds) POST_WRITE(ufds, nfds * sizeof(*ufds));
1905 }
1906}
1907
1908PRE_SYSCALL(select)(long n, __sanitizer___kernel_fd_set *inp,
1909 __sanitizer___kernel_fd_set *outp,
1910 __sanitizer___kernel_fd_set *exp, void *tvp) {}
1911
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) {
1915 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);
1920 }
1921}
1922
1923PRE_SYSCALL(old_select)(void *arg) {}
1924
1925POST_SYSCALL(old_select)(long res, void *arg) {}
1926
1927PRE_SYSCALL(epoll_create)(long size) {}
1928
1929POST_SYSCALL(epoll_create)(long res, long size) {}
1930
1931PRE_SYSCALL(epoll_create1)(long flags) {}
1932
1933POST_SYSCALL(epoll_create1)(long res, long flags) {}
1934
1935PRE_SYSCALL(epoll_ctl)(long epfd, long op, long fd, void *event) {}
1936
1937POST_SYSCALL(epoll_ctl)(long res, long epfd, long op, long fd, void *event) {
1938 if (res >= 0) {
1939 if (event) POST_WRITE(event, struct_epoll_event_sz);
1940 }
1941}
1942
1943PRE_SYSCALL(epoll_wait)(long epfd, void *events, long maxevents, long timeout) {
1944}
1945
1946POST_SYSCALL(epoll_wait)(long res, long epfd, void *events, long maxevents,
1947 long timeout) {
1948 if (res >= 0) {
1949 if (events) POST_WRITE(events, struct_epoll_event_sz);
1950 }
1951}
1952
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);
1956}
1957
1958POST_SYSCALL(epoll_pwait)(long res, long epfd, void *events, long maxevents,
1959 long timeout, const void *sigmask, long sigsetsize) {
1960 if (res >= 0) {
1961 if (events) POST_WRITE(events, struct_epoll_event_sz);
1962 }
1963}
1964
1965PRE_SYSCALL(gethostname)(void *name, long len) {}
1966
1967POST_SYSCALL(gethostname)(long res, void *name, long len) {
1968 if (res >= 0) {
1969 if (name)
1970 POST_WRITE(name, __sanitizer::internal_strlen((const char *)name) + 1);
1971 }
1972}
1973
1974PRE_SYSCALL(sethostname)(void *name, long len) {}
1975
1976POST_SYSCALL(sethostname)(long res, void *name, long len) {
1977 if (res >= 0) {
1978 if (name)
1979 POST_WRITE(name, __sanitizer::internal_strlen((const char *)name) + 1);
1980 }
1981}
1982
1983PRE_SYSCALL(setdomainname)(void *name, long len) {}
1984
1985POST_SYSCALL(setdomainname)(long res, void *name, long len) {
1986 if (res >= 0) {
1987 if (name)
1988 POST_WRITE(name, __sanitizer::internal_strlen((const char *)name) + 1);
1989 }
1990}
1991
1992PRE_SYSCALL(newuname)(void *name) {}
1993
1994POST_SYSCALL(newuname)(long res, void *name) {
1995 if (res >= 0) {
1996 if (name) POST_WRITE(name, struct_new_utsname_sz);
1997 }
1998}
1999
2000PRE_SYSCALL(uname)(void *arg0) {}
2001
2002POST_SYSCALL(uname)(long res, void *arg0) {
2003 if (res >= 0) {
2004 if (arg0) POST_WRITE(arg0, struct_old_utsname_sz);
2005 }
2006}
2007
2008PRE_SYSCALL(olduname)(void *arg0) {}
2009
2010POST_SYSCALL(olduname)(long res, void *arg0) {
2011 if (res >= 0) {
2012 if (arg0) POST_WRITE(arg0, struct_oldold_utsname_sz);
2013 }
2014}
2015
2016PRE_SYSCALL(getrlimit)(long resource, void *rlim) {}
2017
2018POST_SYSCALL(getrlimit)(long res, long resource, void *rlim) {
2019 if (res >= 0) {
2020 if (rlim) POST_WRITE(rlim, struct_rlimit_sz);
2021 }
2022}
2023
2024PRE_SYSCALL(old_getrlimit)(long resource, void *rlim) {}
2025
2026POST_SYSCALL(old_getrlimit)(long res, long resource, void *rlim) {
2027 if (res >= 0) {
2028 if (rlim) POST_WRITE(rlim, struct_rlimit_sz);
2029 }
2030}
2031
2032PRE_SYSCALL(setrlimit)(long resource, void *rlim) {}
2033
2034POST_SYSCALL(setrlimit)(long res, long resource, void *rlim) {
2035 if (res >= 0) {
2036 if (rlim) POST_WRITE(rlim, struct_rlimit_sz);
2037 }
2038}
2039
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);
2044}
2045
2046POST_SYSCALL(prlimit64)(long res, long pid, long resource, const void *new_rlim,
2047 void *old_rlim) {
2048 if (res >= 0) {
2049 if (old_rlim) POST_WRITE(old_rlim, struct_rlimit64_sz);
2050 }
2051}
2052#endif
2053
2054PRE_SYSCALL(getrusage)(long who, void *ru) {}
2055
2056POST_SYSCALL(getrusage)(long res, long who, void *ru) {
2057 if (res >= 0) {
2058 if (ru) POST_WRITE(ru, struct_rusage_sz);
2059 }
2060}
2061
2062PRE_SYSCALL(umask)(long mask) {}
2063
2064POST_SYSCALL(umask)(long res, long mask) {}
2065
2066PRE_SYSCALL(msgget)(long key, long msgflg) {}
2067
2068POST_SYSCALL(msgget)(long res, long key, long msgflg) {}
2069
2070PRE_SYSCALL(msgsnd)(long msqid, void *msgp, long msgsz, long msgflg) {
2071 if (msgp) PRE_READ(msgp, msgsz);
2072}
2073
2074POST_SYSCALL(msgsnd)(long res, long msqid, void *msgp, long msgsz,
2075 long msgflg) {}
2076
2077PRE_SYSCALL(msgrcv)(long msqid, void *msgp, long msgsz, long msgtyp,
2078 long msgflg) {}
2079
2080POST_SYSCALL(msgrcv)(long res, long msqid, void *msgp, long msgsz, long msgtyp,
2081 long msgflg) {
2082 if (res >= 0) {
2083 if (msgp) POST_WRITE(msgp, res);
2084 }
2085}
2086
2087#if !SANITIZER_ANDROID
2088PRE_SYSCALL(msgctl)(long msqid, long cmd, void *buf) {}
2089
2090POST_SYSCALL(msgctl)(long res, long msqid, long cmd, void *buf) {
2091 if (res >= 0) {
2092 if (buf) POST_WRITE(buf, struct_msqid_ds_sz);
2093 }
2094}
2095#endif
2096
2097PRE_SYSCALL(semget)(long key, long nsems, long semflg) {}
2098
2099POST_SYSCALL(semget)(long res, long key, long nsems, long semflg) {}
2100
2101PRE_SYSCALL(semop)(long semid, void *sops, long nsops) {}
2102
2103POST_SYSCALL(semop)(long res, long semid, void *sops, long nsops) {}
2104
2105PRE_SYSCALL(semctl)(long semid, long semnum, long cmd, void *arg) {}
2106
2107POST_SYSCALL(semctl)(long res, long semid, long semnum, long cmd, void *arg) {}
2108
2109PRE_SYSCALL(semtimedop)(long semid, void *sops, long nsops,
2110 const void *timeout) {
2111 if (timeout) PRE_READ(timeout, struct_timespec_sz);
2112}
2113
2114POST_SYSCALL(semtimedop)(long res, long semid, void *sops, long nsops,
2115 const void *timeout) {}
2116
2117PRE_SYSCALL(shmat)(long shmid, void *shmaddr, long shmflg) {}
2118
2119POST_SYSCALL(shmat)(long res, long shmid, void *shmaddr, long shmflg) {
2120 if (res >= 0) {
2121 if (shmaddr)
2122 POST_WRITE(shmaddr,
2123 __sanitizer::internal_strlen((const char *)shmaddr) + 1);
2124 }
2125}
2126
2127PRE_SYSCALL(shmget)(long key, long size, long flag) {}
2128
2129POST_SYSCALL(shmget)(long res, long key, long size, long flag) {}
2130
2131PRE_SYSCALL(shmdt)(void *shmaddr) {}
2132
2133POST_SYSCALL(shmdt)(long res, void *shmaddr) {
2134 if (res >= 0) {
2135 if (shmaddr)
2136 POST_WRITE(shmaddr,
2137 __sanitizer::internal_strlen((const char *)shmaddr) + 1);
2138 }
2139}
2140
2141PRE_SYSCALL(ipc)(long call, long first, long second, long third, void *ptr,
2142 long fifth) {}
2143
2144POST_SYSCALL(ipc)(long res, long call, long first, long second, long third,
2145 void *ptr, long fifth) {}
2146
2147#if !SANITIZER_ANDROID
2148PRE_SYSCALL(shmctl)(long shmid, long cmd, void *buf) {}
2149
2150POST_SYSCALL(shmctl)(long res, long shmid, long cmd, void *buf) {
2151 if (res >= 0) {
2152 if (buf) POST_WRITE(buf, sizeof(__sanitizer_shmid_ds));
2153 }
2154}
2155
2156PRE_SYSCALL(mq_open)(const void *name, long oflag, long mode, void *attr) {
2157 if (name)
2158 PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
2159}
2160
2161POST_SYSCALL(mq_open)(long res, const void *name, long oflag, long mode,
2162 void *attr) {
2163 if (res >= 0) {
2164 if (attr) POST_WRITE(attr, struct_mq_attr_sz);
2165 }
2166}
2167
2168PRE_SYSCALL(mq_unlink)(const void *name) {
2169 if (name)
2170 PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
2171}
2172
2173POST_SYSCALL(mq_unlink)(long res, const void *name) {}
2174
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);
2179}
2180
2181POST_SYSCALL(mq_timedsend)(long res, long mqdes, const void *msg_ptr,
2182 long msg_len, long msg_prio,
2183 const void *abs_timeout) {}
2184
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);
2188}
2189
2190POST_SYSCALL(mq_timedreceive)(long res, long mqdes, void *msg_ptr, long msg_len,
2191 int *msg_prio, const void *abs_timeout) {
2192 if (res >= 0) {
2193 if (msg_ptr) POST_WRITE(msg_ptr, res);
2194 if (msg_prio) POST_WRITE(msg_prio, sizeof(*msg_prio));
2195 }
2196}
2197
2198PRE_SYSCALL(mq_notify)(long mqdes, const void *notification) {
2199 if (notification) PRE_READ(notification, struct_sigevent_sz);
2200}
2201
2202POST_SYSCALL(mq_notify)(long res, long mqdes, const void *notification) {}
2203
2204PRE_SYSCALL(mq_getsetattr)(long mqdes, const void *mqstat, void *omqstat) {
2205 if (mqstat) PRE_READ(mqstat, struct_mq_attr_sz);
2206}
2207
2208POST_SYSCALL(mq_getsetattr)(long res, long mqdes, const void *mqstat,
2209 void *omqstat) {
2210 if (res >= 0) {
2211 if (omqstat) POST_WRITE(omqstat, struct_mq_attr_sz);
2212 }
2213}
2214#endif // SANITIZER_ANDROID
2215
2216PRE_SYSCALL(pciconfig_iobase)(long which, long bus, long devfn) {}
2217
2218POST_SYSCALL(pciconfig_iobase)(long res, long which, long bus, long devfn) {}
2219
2220PRE_SYSCALL(pciconfig_read)(long bus, long dfn, long off, long len, void *buf) {
2221}
2222
2223POST_SYSCALL(pciconfig_read)(long res, long bus, long dfn, long off, long len,
2224 void *buf) {}
2225
2226PRE_SYSCALL(pciconfig_write)(long bus, long dfn, long off, long len,
2227 void *buf) {}
2228
2229POST_SYSCALL(pciconfig_write)(long res, long bus, long dfn, long off, long len,
2230 void *buf) {}
2231
2232PRE_SYSCALL(swapon)(const void *specialfile, long swap_flags) {
2233 if (specialfile)
2234 PRE_READ(specialfile,
2235 __sanitizer::internal_strlen((const char *)specialfile) + 1);
2236}
2237
2238POST_SYSCALL(swapon)(long res, const void *specialfile, long swap_flags) {}
2239
2240PRE_SYSCALL(swapoff)(const void *specialfile) {
2241 if (specialfile)
2242 PRE_READ(specialfile,
2243 __sanitizer::internal_strlen((const char *)specialfile) + 1);
2244}
2245
2246POST_SYSCALL(swapoff)(long res, const void *specialfile) {}
2247
2248PRE_SYSCALL(sysctl)(__sanitizer___sysctl_args *args) {
2249 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);
2252 }
2253}
2254
2255POST_SYSCALL(sysctl)(long res, __sanitizer___sysctl_args *args) {
2256 if (res >= 0) {
2257 if (args && args->oldval && args->oldlenp) {
2258 POST_WRITE(args->oldlenp, sizeof(*args->oldlenp));
2259 POST_WRITE(args->oldval, *args->oldlenp);
2260 }
2261 }
2262}
2263
2264PRE_SYSCALL(sysinfo)(void *info) {}
2265
2266POST_SYSCALL(sysinfo)(long res, void *info) {
2267 if (res >= 0) {
2268 if (info) POST_WRITE(info, struct_sysinfo_sz);
2269 }
2270}
2271
2272PRE_SYSCALL(sysfs)(long option, long arg1, long arg2) {}
2273
2274POST_SYSCALL(sysfs)(long res, long option, long arg1, long arg2) {}
2275
2276PRE_SYSCALL(syslog)(long type, void *buf, long len) {}
2277
2278POST_SYSCALL(syslog)(long res, long type, void *buf, long len) {
2279 if (res >= 0) {
2280 if (buf)
2281 POST_WRITE(buf, __sanitizer::internal_strlen((const char *)buf) + 1);
2282 }
2283}
2284
2285PRE_SYSCALL(uselib)(const void *library) {
2286 if (library)
2287 PRE_READ(library, __sanitizer::internal_strlen((const char *)library) + 1);
2288}
2289
2290POST_SYSCALL(uselib)(long res, const void *library) {}
2291
2292PRE_SYSCALL(ni_syscall)() {}
2293
2294POST_SYSCALL(ni_syscall)(long res) {}
2295
2296PRE_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 if (data) {
2301 if (request == ptrace_setregs) {
2302 PRE_READ((void *)data, struct_user_regs_struct_sz);
2303 } else if (request == ptrace_setfpregs) {
2304 PRE_READ((void *)data, struct_user_fpregs_struct_sz);
2305 } else if (request == ptrace_setfpxregs) {
2306 PRE_READ((void *)data, struct_user_fpxregs_struct_sz);
2307 } else if (request == ptrace_setsiginfo) {
2308 PRE_READ((void *)data, siginfo_t_sz);
2309 } else if (request == ptrace_setregset) {
2310 __sanitizer_iovec *iov = (__sanitizer_iovec *)data;
2311 PRE_READ(iov->iov_base, iov->iov_len);
2312 }
2313 }
2314#endif
2315}
2316
2317POST_SYSCALL(ptrace)(long res, long request, long pid, long addr, long data) {
2318#if !SANITIZER_ANDROID && \
2319 (defined(__i386) || defined(__x86_64) || defined(__mips64) || \
2320 defined(__powerpc64__) || defined(__aarch64__) || defined(__s390__))
2321 if (res >= 0 && data) {
2322 // Note that this is different from the interceptor in
2323 // sanitizer_common_interceptors.inc.
2324 // PEEK* requests return resulting values through data pointer.
2325 if (request == ptrace_getregs) {
2326 POST_WRITE((void *)data, struct_user_regs_struct_sz);
2327 } else if (request == ptrace_getfpregs) {
2328 POST_WRITE((void *)data, struct_user_fpregs_struct_sz);
2329 } else if (request == ptrace_getfpxregs) {
2330 POST_WRITE((void *)data, struct_user_fpxregs_struct_sz);
2331 } else if (request == ptrace_getsiginfo) {
2332 POST_WRITE((void *)data, siginfo_t_sz);
2333 } else if (request == ptrace_getregset) {
2334 __sanitizer_iovec *iov = (__sanitizer_iovec *)data;
2335 POST_WRITE(iov->iov_base, iov->iov_len);
2336 } else if (request == ptrace_peekdata || request == ptrace_peektext ||
2337 request == ptrace_peekuser) {
2338 POST_WRITE((void *)data, sizeof(void *));
2339 }
2340 }
2341#endif
2342}
2343
2344PRE_SYSCALL(add_key)(const void *_type, const void *_description,
2345 const void *_payload, long plen, long destringid) {
2346 if (_type)
2347 PRE_READ(_type, __sanitizer::internal_strlen((const char *)_type) + 1);
2348 if (_description)
2349 PRE_READ(_description,
2350 __sanitizer::internal_strlen((const char *)_description) + 1);
2351}
2352
2353POST_SYSCALL(add_key)(long res, const void *_type, const void *_description,
2354 const void *_payload, long plen, long destringid) {}
2355
2356PRE_SYSCALL(request_key)(const void *_type, const void *_description,
2357 const void *_callout_info, long destringid) {
2358 if (_type)
2359 PRE_READ(_type, __sanitizer::internal_strlen((const char *)_type) + 1);
2360 if (_description)
2361 PRE_READ(_description,
2362 __sanitizer::internal_strlen((const char *)_description) + 1);
2363 if (_callout_info)
2364 PRE_READ(_callout_info,
2365 __sanitizer::internal_strlen((const char *)_callout_info) + 1);
2366}
2367
2368POST_SYSCALL(request_key)(long res, const void *_type, const void *_description,
2369 const void *_callout_info, long destringid) {}
2370
2371PRE_SYSCALL(keyctl)(long cmd, long arg2, long arg3, long arg4, long arg5) {}
2372
2373POST_SYSCALL(keyctl)(long res, long cmd, long arg2, long arg3, long arg4,
2374 long arg5) {}
2375
2376PRE_SYSCALL(ioprio_set)(long which, long who, long ioprio) {}
2377
2378POST_SYSCALL(ioprio_set)(long res, long which, long who, long ioprio) {}
2379
2380PRE_SYSCALL(ioprio_get)(long which, long who) {}
2381
2382POST_SYSCALL(ioprio_get)(long res, long which, long who) {}
2383
2384PRE_SYSCALL(set_mempolicy)(long mode, void *nmask, long maxnode) {}
2385
2386POST_SYSCALL(set_mempolicy)(long res, long mode, void *nmask, long maxnode) {
2387 if (res >= 0) {
2388 if (nmask) POST_WRITE(nmask, sizeof(long));
2389 }
2390}
2391
2392PRE_SYSCALL(migrate_pages)(long pid, long maxnode, const void *from,
2393 const void *to) {
2394 if (from) PRE_READ(from, sizeof(long));
2395 if (to) PRE_READ(to, sizeof(long));
2396}
2397
2398POST_SYSCALL(migrate_pages)(long res, long pid, long maxnode, const void *from,
2399 const void *to) {}
2400
2401PRE_SYSCALL(move_pages)(long pid, long nr_pages, const void **pages,
2402 const int *nodes, int *status, long flags) {
2403 if (pages) PRE_READ(pages, nr_pages * sizeof(*pages));
2404 if (nodes) PRE_READ(nodes, nr_pages * sizeof(*nodes));
2405}
2406
2407POST_SYSCALL(move_pages)(long res, long pid, long nr_pages, const void **pages,
2408 const int *nodes, int *status, long flags) {
2409 if (res >= 0) {
2410 if (status) POST_WRITE(status, nr_pages * sizeof(*status));
2411 }
2412}
2413
2414PRE_SYSCALL(mbind)(long start, long len, long mode, void *nmask, long maxnode,
2415 long flags) {}
2416
2417POST_SYSCALL(mbind)(long res, long start, long len, long mode, void *nmask,
2418 long maxnode, long flags) {
2419 if (res >= 0) {
2420 if (nmask) POST_WRITE(nmask, sizeof(long));
2421 }
2422}
2423
2424PRE_SYSCALL(get_mempolicy)(void *policy, void *nmask, long maxnode, long addr,
2425 long flags) {}
2426
2427POST_SYSCALL(get_mempolicy)(long res, void *policy, void *nmask, long maxnode,
2428 long addr, long flags) {
2429 if (res >= 0) {
2430 if (policy) POST_WRITE(policy, sizeof(int));
2431 if (nmask) POST_WRITE(nmask, sizeof(long));
2432 }
2433}
2434
2435PRE_SYSCALL(inotify_init)() {}
2436
2437POST_SYSCALL(inotify_init)(long res) {}
2438
2439PRE_SYSCALL(inotify_init1)(long flags) {}
2440
2441POST_SYSCALL(inotify_init1)(long res, long flags) {}
2442
2443PRE_SYSCALL(inotify_add_watch)(long fd, const void *path, long mask) {
2444 if (path)
2445 PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
2446}
2447
2448POST_SYSCALL(inotify_add_watch)(long res, long fd, const void *path,
2449 long mask) {}
2450
2451PRE_SYSCALL(inotify_rm_watch)(long fd, long wd) {}
2452
2453POST_SYSCALL(inotify_rm_watch)(long res, long fd, long wd) {}
2454
2455PRE_SYSCALL(spu_run)(long fd, void *unpc, void *ustatus) {}
2456
2457POST_SYSCALL(spu_run)(long res, long fd, unsigned *unpc, unsigned *ustatus) {
2458 if (res >= 0) {
2459 if (unpc) POST_WRITE(unpc, sizeof(*unpc));
2460 if (ustatus) POST_WRITE(ustatus, sizeof(*ustatus));
2461 }
2462}
2463
2464PRE_SYSCALL(spu_create)(const void *name, long flags, long mode, long fd) {
2465 if (name)
2466 PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
2467}
2468
2469POST_SYSCALL(spu_create)(long res, const void *name, long flags, long mode,
2470 long fd) {}
2471
2472PRE_SYSCALL(mknodat)(long dfd, const void *filename, long mode, long dev) {
2473 if (filename)
2474 PRE_READ(filename,
2475 __sanitizer::internal_strlen((const char *)filename) + 1);
2476}
2477
2478POST_SYSCALL(mknodat)(long res, long dfd, const void *filename, long mode,
2479 long dev) {}
2480
2481PRE_SYSCALL(mkdirat)(long dfd, const void *pathname, long mode) {
2482 if (pathname)
2483 PRE_READ(pathname,
2484 __sanitizer::internal_strlen((const char *)pathname) + 1);
2485}
2486
2487POST_SYSCALL(mkdirat)(long res, long dfd, const void *pathname, long mode) {}
2488
2489PRE_SYSCALL(unlinkat)(long dfd, const void *pathname, long flag) {
2490 if (pathname)
2491 PRE_READ(pathname,
2492 __sanitizer::internal_strlen((const char *)pathname) + 1);
2493}
2494
2495POST_SYSCALL(unlinkat)(long res, long dfd, const void *pathname, long flag) {}
2496
2497PRE_SYSCALL(symlinkat)(const void *oldname, long newdfd, const void *newname) {
2498 if (oldname)
2499 PRE_READ(oldname, __sanitizer::internal_strlen((const char *)oldname) + 1);
2500 if (newname)
2501 PRE_READ(newname, __sanitizer::internal_strlen((const char *)newname) + 1);
2502}
2503
2504POST_SYSCALL(symlinkat)(long res, const void *oldname, long newdfd,
2505 const void *newname) {}
2506
2507PRE_SYSCALL(linkat)(long olddfd, const void *oldname, long newdfd,
2508 const void *newname, long flags) {
2509 if (oldname)
2510 PRE_READ(oldname, __sanitizer::internal_strlen((const char *)oldname) + 1);
2511 if (newname)
2512 PRE_READ(newname, __sanitizer::internal_strlen((const char *)newname) + 1);
2513}
2514
2515POST_SYSCALL(linkat)(long res, long olddfd, const void *oldname, long newdfd,
2516 const void *newname, long flags) {}
2517
2518PRE_SYSCALL(renameat)(long olddfd, const void *oldname, long newdfd,
2519 const void *newname) {
2520 if (oldname)
2521 PRE_READ(oldname, __sanitizer::internal_strlen((const char *)oldname) + 1);
2522 if (newname)
2523 PRE_READ(newname, __sanitizer::internal_strlen((const char *)newname) + 1);
2524}
2525
2526POST_SYSCALL(renameat)(long res, long olddfd, const void *oldname, long newdfd,
2527 const void *newname) {}
2528
2529PRE_SYSCALL(futimesat)(long dfd, const void *filename, void *utimes) {
2530 if (filename)
2531 PRE_READ(filename,
2532 __sanitizer::internal_strlen((const char *)filename) + 1);
2533}
2534
2535POST_SYSCALL(futimesat)(long res, long dfd, const void *filename,
2536 void *utimes) {
2537 if (res >= 0) {
2538 if (utimes) POST_WRITE(utimes, timeval_sz);
2539 }
2540}
2541
2542PRE_SYSCALL(faccessat)(long dfd, const void *filename, long mode) {
2543 if (filename)
2544 PRE_READ(filename,
2545 __sanitizer::internal_strlen((const char *)filename) + 1);
2546}
2547
2548POST_SYSCALL(faccessat)(long res, long dfd, const void *filename, long mode) {}
2549
2550PRE_SYSCALL(fchmodat)(long dfd, const void *filename, long mode) {
2551 if (filename)
2552 PRE_READ(filename,
2553 __sanitizer::internal_strlen((const char *)filename) + 1);
2554}
2555
2556POST_SYSCALL(fchmodat)(long res, long dfd, const void *filename, long mode) {}
2557
2558PRE_SYSCALL(fchownat)(long dfd, const void *filename, long user, long group,
2559 long flag) {
2560 if (filename)
2561 PRE_READ(filename,
2562 __sanitizer::internal_strlen((const char *)filename) + 1);
2563}
2564
2565POST_SYSCALL(fchownat)(long res, long dfd, const void *filename, long user,
2566 long group, long flag) {}
2567
2568PRE_SYSCALL(openat)(long dfd, const void *filename, long flags, long mode) {
2569 if (filename)
2570 PRE_READ(filename,
2571 __sanitizer::internal_strlen((const char *)filename) + 1);
2572}
2573
2574POST_SYSCALL(openat)(long res, long dfd, const void *filename, long flags,
2575 long mode) {}
2576
2577PRE_SYSCALL(newfstatat)(long dfd, const void *filename, void *statbuf,
2578 long flag) {
2579 if (filename)
2580 PRE_READ(filename,
2581 __sanitizer::internal_strlen((const char *)filename) + 1);
2582}
2583
2584POST_SYSCALL(newfstatat)(long res, long dfd, const void *filename,
2585 void *statbuf, long flag) {
2586 if (res >= 0) {
2587 if (statbuf) POST_WRITE(statbuf, struct_kernel_stat_sz);
2588 }
2589}
2590
2591PRE_SYSCALL(fstatat64)(long dfd, const void *filename, void *statbuf,
2592 long flag) {
2593 if (filename)
2594 PRE_READ(filename,
2595 __sanitizer::internal_strlen((const char *)filename) + 1);
2596}
2597
2598POST_SYSCALL(fstatat64)(long res, long dfd, const void *filename, void *statbuf,
2599 long flag) {
2600 if (res >= 0) {
2601 if (statbuf) POST_WRITE(statbuf, struct_kernel_stat64_sz);
2602 }
2603}
2604
2605PRE_SYSCALL(readlinkat)(long dfd, const void *path, void *buf, long bufsiz) {
2606 if (path)
2607 PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
2608}
2609
2610POST_SYSCALL(readlinkat)(long res, long dfd, const void *path, void *buf,
2611 long bufsiz) {
2612 if (res >= 0) {
2613 if (buf)
2614 POST_WRITE(buf, __sanitizer::internal_strlen((const char *)buf) + 1);
2615 }
2616}
2617
2618PRE_SYSCALL(utimensat)(long dfd, const void *filename, void *utimes,
2619 long flags) {
2620 if (filename)
2621 PRE_READ(filename,
2622 __sanitizer::internal_strlen((const char *)filename) + 1);
2623}
2624
2625POST_SYSCALL(utimensat)(long res, long dfd, const void *filename, void *utimes,
2626 long flags) {
2627 if (res >= 0) {
2628 if (utimes) POST_WRITE(utimes, struct_timespec_sz);
2629 }
2630}
2631
2632PRE_SYSCALL(unshare)(long unshare_flags) {}
2633
2634POST_SYSCALL(unshare)(long res, long unshare_flags) {}
2635
2636PRE_SYSCALL(splice)(long fd_in, void *off_in, long fd_out, void *off_out,
2637 long len, long flags) {}
2638
2639POST_SYSCALL(splice)(long res, long fd_in, void *off_in, long fd_out,
2640 void *off_out, long len, long flags) {
2641 if (res >= 0) {
2642 if (off_in) POST_WRITE(off_in, sizeof(long long));
2643 if (off_out) POST_WRITE(off_out, sizeof(long long));
2644 }
2645}
2646
2647PRE_SYSCALL(vmsplice)(long fd, const __sanitizer_iovec *iov, long nr_segs,
2648 long flags) {}
2649
2650POST_SYSCALL(vmsplice)(long res, long fd, const __sanitizer_iovec *iov,
2651 long nr_segs, long flags) {
2652 if (res >= 0) {
2653 if (iov) kernel_read_iovec(iov, nr_segs, res);
2654 }
2655}
2656
2657PRE_SYSCALL(tee)(long fdin, long fdout, long len, long flags) {}
2658
2659POST_SYSCALL(tee)(long res, long fdin, long fdout, long len, long flags) {}
2660
2661PRE_SYSCALL(get_robust_list)(long pid, void *head_ptr, void *len_ptr) {}
2662
2663POST_SYSCALL(get_robust_list)(long res, long pid, void *head_ptr,
2664 void *len_ptr) {}
2665
2666PRE_SYSCALL(set_robust_list)(void *head, long len) {}
2667
2668POST_SYSCALL(set_robust_list)(long res, void *head, long len) {}
2669
2670PRE_SYSCALL(getcpu)(void *cpu, void *node, void *cache) {}
2671
2672POST_SYSCALL(getcpu)(long res, void *cpu, void *node, void *cache) {
2673 if (res >= 0) {
2674 if (cpu) POST_WRITE(cpu, sizeof(unsigned));
2675 if (node) POST_WRITE(node, sizeof(unsigned));
2676 // The third argument to this system call is nowadays unused.
2677 }
2678}
2679
2680PRE_SYSCALL(signalfd)(long ufd, void *user_mask, long sizemask) {}
2681
2682POST_SYSCALL(signalfd)(long res, long ufd, kernel_sigset_t *user_mask,
2683 long sizemask) {
2684 if (res >= 0) {
2685 if (user_mask) POST_WRITE(user_mask, sizemask);
2686 }
2687}
2688
2689PRE_SYSCALL(signalfd4)(long ufd, void *user_mask, long sizemask, long flags) {}
2690
2691POST_SYSCALL(signalfd4)(long res, long ufd, kernel_sigset_t *user_mask,
2692 long sizemask, long flags) {
2693 if (res >= 0) {
2694 if (user_mask) POST_WRITE(user_mask, sizemask);
2695 }
2696}
2697
2698PRE_SYSCALL(timerfd_create)(long clockid, long flags) {}
2699
2700POST_SYSCALL(timerfd_create)(long res, long clockid, long flags) {}
2701
2702PRE_SYSCALL(timerfd_settime)(long ufd, long flags, const void *utmr,
2703 void *otmr) {
2704 if (utmr) PRE_READ(utmr, struct_itimerspec_sz);
2705}
2706
2707POST_SYSCALL(timerfd_settime)(long res, long ufd, long flags, const void *utmr,
2708 void *otmr) {
2709 if (res >= 0) {
2710 if (otmr) POST_WRITE(otmr, struct_itimerspec_sz);
2711 }
2712}
2713
2714PRE_SYSCALL(timerfd_gettime)(long ufd, void *otmr) {}
2715
2716POST_SYSCALL(timerfd_gettime)(long res, long ufd, void *otmr) {
2717 if (res >= 0) {
2718 if (otmr) POST_WRITE(otmr, struct_itimerspec_sz);
2719 }
2720}
2721
2722PRE_SYSCALL(eventfd)(long count) {}
2723
2724POST_SYSCALL(eventfd)(long res, long count) {}
2725
2726PRE_SYSCALL(eventfd2)(long count, long flags) {}
2727
2728POST_SYSCALL(eventfd2)(long res, long count, long flags) {}
2729
2730PRE_SYSCALL(old_readdir)(long arg0, void *arg1, long arg2) {}
2731
2732POST_SYSCALL(old_readdir)(long res, long arg0, void *arg1, long arg2) {
2733 // Missing definition of 'struct old_linux_dirent'.
2734}
2735
2736PRE_SYSCALL(pselect6)(long arg0, __sanitizer___kernel_fd_set *arg1,
2737 __sanitizer___kernel_fd_set *arg2,
2738 __sanitizer___kernel_fd_set *arg3, void *arg4,
2739 void *arg5) {}
2740
2741POST_SYSCALL(pselect6)(long res, long arg0, __sanitizer___kernel_fd_set *arg1,
2742 __sanitizer___kernel_fd_set *arg2,
2743 __sanitizer___kernel_fd_set *arg3, void *arg4,
2744 void *arg5) {
2745 if (res >= 0) {
2746 if (arg1) POST_WRITE(arg1, sizeof(*arg1));
2747 if (arg2) POST_WRITE(arg2, sizeof(*arg2));
2748 if (arg3) POST_WRITE(arg3, sizeof(*arg3));
2749 if (arg4) POST_WRITE(arg4, struct_timespec_sz);
2750 }
2751}
2752
2753PRE_SYSCALL(ppoll)(__sanitizer_pollfd *arg0, long arg1, void *arg2,
2754 const kernel_sigset_t *arg3, long arg4) {
2755 if (arg3) PRE_READ(arg3, arg4);
2756}
2757
2758POST_SYSCALL(ppoll)(long res, __sanitizer_pollfd *arg0, long arg1, void *arg2,
2759 const void *arg3, long arg4) {
2760 if (res >= 0) {
2761 if (arg0) POST_WRITE(arg0, sizeof(*arg0));
2762 if (arg2) POST_WRITE(arg2, struct_timespec_sz);
2763 }
2764}
2765
2766PRE_SYSCALL(syncfs)(long fd) {}
2767
2768POST_SYSCALL(syncfs)(long res, long fd) {}
2769
2770PRE_SYSCALL(perf_event_open)(__sanitizer_perf_event_attr *attr_uptr, long pid,
2771 long cpu, long group_fd, long flags) {
2772 if (attr_uptr) PRE_READ(attr_uptr, attr_uptr->size);
2773}
2774
2775POST_SYSCALL(perf_event_open)(long res, __sanitizer_perf_event_attr *attr_uptr,
2776 long pid, long cpu, long group_fd, long flags) {}
2777
2778PRE_SYSCALL(mmap_pgoff)(long addr, long len, long prot, long flags, long fd,
2779 long pgoff) {}
2780
2781POST_SYSCALL(mmap_pgoff)(long res, long addr, long len, long prot, long flags,
2782 long fd, long pgoff) {}
2783
2784PRE_SYSCALL(old_mmap)(void *arg) {}
2785
2786POST_SYSCALL(old_mmap)(long res, void *arg) {}
2787
2788PRE_SYSCALL(name_to_handle_at)(long dfd, const void *name, void *handle,
2789 void *mnt_id, long flag) {}
2790
2791POST_SYSCALL(name_to_handle_at)(long res, long dfd, const void *name,
2792 void *handle, void *mnt_id, long flag) {}
2793
2794PRE_SYSCALL(open_by_handle_at)(long mountdirfd, void *handle, long flags) {}
2795
2796POST_SYSCALL(open_by_handle_at)(long res, long mountdirfd, void *handle,
2797 long flags) {}
2798
2799PRE_SYSCALL(setns)(long fd, long nstype) {}
2800
2801POST_SYSCALL(setns)(long res, long fd, long nstype) {}
2802
2803PRE_SYSCALL(process_vm_readv)(long pid, const __sanitizer_iovec *lvec,
2804 long liovcnt, const void *rvec, long riovcnt,
2805 long flags) {}
2806
2807POST_SYSCALL(process_vm_readv)(long res, long pid,
2808 const __sanitizer_iovec *lvec, long liovcnt,
2809 const void *rvec, long riovcnt, long flags) {
2810 if (res >= 0) {
2811 if (lvec) kernel_write_iovec(lvec, liovcnt, res);
2812 }
2813}
2814
2815PRE_SYSCALL(process_vm_writev)(long pid, const __sanitizer_iovec *lvec,
2816 long liovcnt, const void *rvec, long riovcnt,
2817 long flags) {}
2818
2819POST_SYSCALL(process_vm_writev)(long res, long pid,
2820 const __sanitizer_iovec *lvec, long liovcnt,
2821 const void *rvec, long riovcnt, long flags) {
2822 if (res >= 0) {
2823 if (lvec) kernel_read_iovec(lvec, liovcnt, res);
2824 }
2825}
2826
2827PRE_SYSCALL(fork)() {
2828 COMMON_SYSCALL_PRE_FORK();
2829}
2830
2831POST_SYSCALL(fork)(long res) {
2832 COMMON_SYSCALL_POST_FORK(res);
2833}
2834
2835PRE_SYSCALL(vfork)() {
2836 COMMON_SYSCALL_PRE_FORK();
2837}
2838
2839POST_SYSCALL(vfork)(long res) {
2840 COMMON_SYSCALL_POST_FORK(res);
2841}
2842
2843PRE_SYSCALL(sigaction)(long signum, const __sanitizer_kernel_sigaction_t *act,
2844 __sanitizer_kernel_sigaction_t *oldact) {
2845 if (act) {
2846 PRE_READ(&act->sigaction, sizeof(act->sigaction));
2847 PRE_READ(&act->sa_flags, sizeof(act->sa_flags));
2848 PRE_READ(&act->sa_mask, sizeof(act->sa_mask));
2849 }
2850}
2851
2852POST_SYSCALL(sigaction)(long res, long signum,
2853 const __sanitizer_kernel_sigaction_t *act,
2854 __sanitizer_kernel_sigaction_t *oldact) {
2855 if (res >= 0 && oldact) POST_WRITE(oldact, sizeof(*oldact));
2856}
2857
2858PRE_SYSCALL(rt_sigaction)(long signum,
2859 const __sanitizer_kernel_sigaction_t *act,
2860 __sanitizer_kernel_sigaction_t *oldact, SIZE_T sz) {
2861 if (act) {
2862 PRE_READ(&act->sigaction, sizeof(act->sigaction));
2863 PRE_READ(&act->sa_flags, sizeof(act->sa_flags));
2864 PRE_READ(&act->sa_mask, sz);
2865 }
2866}
2867
2868POST_SYSCALL(rt_sigaction)(long res, long signum,
2869 const __sanitizer_kernel_sigaction_t *act,
2870 __sanitizer_kernel_sigaction_t *oldact, SIZE_T sz) {
2871 if (res >= 0 && oldact) {
2872 SIZE_T oldact_sz = ((char *)&oldact->sa_mask) - ((char *)oldact) + sz;
2873 POST_WRITE(oldact, oldact_sz);
2874 }
2875}
2876
2877PRE_SYSCALL(getrandom)(void *buf, uptr count, long flags) {
2878 if (buf) {
2879 PRE_WRITE(buf, count);
2880 }
2881}
2882
2883POST_SYSCALL(getrandom)(long res, void *buf, uptr count, long flags) {
2884 if (res > 0 && buf) {
2885 POST_WRITE(buf, res);
2886 }
2887}
2888
2889PRE_SYSCALL(sigaltstack)(const void *ss, void *oss) {
2890 if (ss != nullptr) {
2891 PRE_READ(ss, struct_stack_t_sz);
2892 }
2893 if (oss != nullptr) {
2894 PRE_WRITE(oss, struct_stack_t_sz);
2895 }
2896}
2897
2898POST_SYSCALL(sigaltstack)(long res, void *ss, void *oss) {
2899 if (res == 0) {
2900 if (oss != nullptr) {
2901 POST_WRITE(oss, struct_stack_t_sz);
2902 }
2903 }
2904}
2905} // extern "C"
2906
2907#undef PRE_SYSCALL
2908#undef PRE_READ
2909#undef PRE_WRITE
2910#undef POST_SYSCALL
2911#undef POST_READ
2912#undef POST_WRITE
2913
2914#endif // SANITIZER_LINUX
lib/tsan/sanitizer_common/sanitizer_coverage_interface.inc created+33
...@@ -0,0 +1,33 @@
1//===-- sanitizer_coverage_interface.inc ----------------------------------===//
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// Sanitizer Coverage interface list.
9//===----------------------------------------------------------------------===//
10INTERFACE_FUNCTION(__sanitizer_cov_dump)
11INTERFACE_FUNCTION(__sanitizer_cov_reset)
12INTERFACE_FUNCTION(__sanitizer_dump_coverage)
13INTERFACE_FUNCTION(__sanitizer_dump_trace_pc_guard_coverage)
14INTERFACE_WEAK_FUNCTION(__sancov_default_options)
15INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp)
16INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp1)
17INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp2)
18INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp4)
19INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp8)
20INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_const_cmp1)
21INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_const_cmp2)
22INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_const_cmp4)
23INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_const_cmp8)
24INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_div4)
25INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_div8)
26INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_gep)
27INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_pc_guard)
28INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_pc_guard_init)
29INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_pc_indir)
30INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_switch)
31INTERFACE_WEAK_FUNCTION(__sanitizer_cov_8bit_counters_init)
32INTERFACE_WEAK_FUNCTION(__sanitizer_cov_bool_flag_init)
33INTERFACE_WEAK_FUNCTION(__sanitizer_cov_pcs_init)
lib/tsan/sanitizer_common/sanitizer_dbghelp.h created+41
...@@ -0,0 +1,41 @@
1//===-- sanitizer_dbghelp.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// Wrappers for lazy loaded dbghelp.dll. Provides function pointers and a
10// callback to initialize them.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef SANITIZER_SYMBOLIZER_WIN_H
15#define SANITIZER_SYMBOLIZER_WIN_H
16
17#if !SANITIZER_WINDOWS
18#error "sanitizer_dbghelp.h is a Windows-only header"
19#endif
20
21#define WIN32_LEAN_AND_MEAN
22#include <windows.h>
23#include <dbghelp.h>
24
25namespace __sanitizer {
26
27extern decltype(::StackWalk64) *StackWalk64;
28extern decltype(::SymCleanup) *SymCleanup;
29extern decltype(::SymFromAddr) *SymFromAddr;
30extern decltype(::SymFunctionTableAccess64) *SymFunctionTableAccess64;
31extern decltype(::SymGetLineFromAddr64) *SymGetLineFromAddr64;
32extern decltype(::SymGetModuleBase64) *SymGetModuleBase64;
33extern decltype(::SymGetSearchPathW) *SymGetSearchPathW;
34extern decltype(::SymInitialize) *SymInitialize;
35extern decltype(::SymSetOptions) *SymSetOptions;
36extern decltype(::SymSetSearchPathW) *SymSetSearchPathW;
37extern decltype(::UnDecorateSymbolName) *UnDecorateSymbolName;
38
39} // namespace __sanitizer
40
41#endif // SANITIZER_SYMBOLIZER_WIN_H
lib/tsan/sanitizer_common/sanitizer_deadlock_detector.h created+410
...@@ -0,0 +1,410 @@
1//===-- sanitizer_deadlock_detector.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.
10// The deadlock detector maintains a directed graph of lock acquisitions.
11// When a lock event happens, the detector checks if the locks already held by
12// the current thread are reachable from the newly acquired lock.
13//
14// The detector can handle only a fixed amount of simultaneously live locks
15// (a lock is alive if it has been locked at least once and has not been
16// destroyed). When the maximal number of locks is reached the entire graph
17// is flushed and the new lock epoch is started. The node ids from the old
18// epochs can not be used with any of the detector methods except for
19// nodeBelongsToCurrentEpoch().
20//
21// FIXME: this is work in progress, nothing really works yet.
22//
23//===----------------------------------------------------------------------===//
24
25#ifndef SANITIZER_DEADLOCK_DETECTOR_H
26#define SANITIZER_DEADLOCK_DETECTOR_H
27
28#include "sanitizer_bvgraph.h"
29#include "sanitizer_common.h"
30
31namespace __sanitizer {
32
33// Thread-local state for DeadlockDetector.
34// It contains the locks currently held by the owning thread.
35template <class BV>
36class DeadlockDetectorTLS {
37 public:
38 // No CTOR.
39 void clear() {
40 bv_.clear();
41 epoch_ = 0;
42 n_recursive_locks = 0;
43 n_all_locks_ = 0;
44 }
45
46 bool empty() const { return bv_.empty(); }
47
48 void ensureCurrentEpoch(uptr current_epoch) {
49 if (epoch_ == current_epoch) return;
50 bv_.clear();
51 epoch_ = current_epoch;
52 n_recursive_locks = 0;
53 n_all_locks_ = 0;
54 }
55
56 uptr getEpoch() const { return epoch_; }
57
58 // Returns true if this is the first (non-recursive) acquisition of this lock.
59 bool addLock(uptr lock_id, uptr current_epoch, u32 stk) {
60 CHECK_EQ(epoch_, current_epoch);
61 if (!bv_.setBit(lock_id)) {
62 // The lock is already held by this thread, it must be recursive.
63 CHECK_LT(n_recursive_locks, ARRAY_SIZE(recursive_locks));
64 recursive_locks[n_recursive_locks++] = lock_id;
65 return false;
66 }
67 CHECK_LT(n_all_locks_, ARRAY_SIZE(all_locks_with_contexts_));
68 // lock_id < BV::kSize, can cast to a smaller int.
69 u32 lock_id_short = static_cast<u32>(lock_id);
70 LockWithContext l = {lock_id_short, stk};
71 all_locks_with_contexts_[n_all_locks_++] = l;
72 return true;
73 }
74
75 void removeLock(uptr lock_id) {
76 if (n_recursive_locks) {
77 for (sptr i = n_recursive_locks - 1; i >= 0; i--) {
78 if (recursive_locks[i] == lock_id) {
79 n_recursive_locks--;
80 Swap(recursive_locks[i], recursive_locks[n_recursive_locks]);
81 return;
82 }
83 }
84 }
85 if (!bv_.clearBit(lock_id))
86 return; // probably addLock happened before flush
87 if (n_all_locks_) {
88 for (sptr i = n_all_locks_ - 1; i >= 0; i--) {
89 if (all_locks_with_contexts_[i].lock == static_cast<u32>(lock_id)) {
90 Swap(all_locks_with_contexts_[i],
91 all_locks_with_contexts_[n_all_locks_ - 1]);
92 n_all_locks_--;
93 break;
94 }
95 }
96 }
97 }
98
99 u32 findLockContext(uptr lock_id) {
100 for (uptr i = 0; i < n_all_locks_; i++)
101 if (all_locks_with_contexts_[i].lock == static_cast<u32>(lock_id))
102 return all_locks_with_contexts_[i].stk;
103 return 0;
104 }
105
106 const BV &getLocks(uptr current_epoch) const {
107 CHECK_EQ(epoch_, current_epoch);
108 return bv_;
109 }
110
111 uptr getNumLocks() const { return n_all_locks_; }
112 uptr getLock(uptr idx) const { return all_locks_with_contexts_[idx].lock; }
113
114 private:
115 BV bv_;
116 uptr epoch_;
117 uptr recursive_locks[64];
118 uptr n_recursive_locks;
119 struct LockWithContext {
120 u32 lock;
121 u32 stk;
122 };
123 LockWithContext all_locks_with_contexts_[64];
124 uptr n_all_locks_;
125};
126
127// DeadlockDetector.
128// For deadlock detection to work we need one global DeadlockDetector object
129// and one DeadlockDetectorTLS object per evey thread.
130// This class is not thread safe, all concurrent accesses should be guarded
131// by an external lock.
132// Most of the methods of this class are not thread-safe (i.e. should
133// be protected by an external lock) unless explicitly told otherwise.
134template <class BV>
135class DeadlockDetector {
136 public:
137 typedef BV BitVector;
138
139 uptr size() const { return g_.size(); }
140
141 // No CTOR.
142 void clear() {
143 current_epoch_ = 0;
144 available_nodes_.clear();
145 recycled_nodes_.clear();
146 g_.clear();
147 n_edges_ = 0;
148 }
149
150 // Allocate new deadlock detector node.
151 // If we are out of available nodes first try to recycle some.
152 // If there is nothing to recycle, flush the graph and increment the epoch.
153 // Associate 'data' (opaque user's object) with the new node.
154 uptr newNode(uptr data) {
155 if (!available_nodes_.empty())
156 return getAvailableNode(data);
157 if (!recycled_nodes_.empty()) {
158 for (sptr i = n_edges_ - 1; i >= 0; i--) {
159 if (recycled_nodes_.getBit(edges_[i].from) ||
160 recycled_nodes_.getBit(edges_[i].to)) {
161 Swap(edges_[i], edges_[n_edges_ - 1]);
162 n_edges_--;
163 }
164 }
165 CHECK(available_nodes_.empty());
166 // removeEdgesFrom was called in removeNode.
167 g_.removeEdgesTo(recycled_nodes_);
168 available_nodes_.setUnion(recycled_nodes_);
169 recycled_nodes_.clear();
170 return getAvailableNode(data);
171 }
172 // We are out of vacant nodes. Flush and increment the current_epoch_.
173 current_epoch_ += size();
174 recycled_nodes_.clear();
175 available_nodes_.setAll();
176 g_.clear();
177 n_edges_ = 0;
178 return getAvailableNode(data);
179 }
180
181 // Get data associated with the node created by newNode().
182 uptr getData(uptr node) const { return data_[nodeToIndex(node)]; }
183
184 bool nodeBelongsToCurrentEpoch(uptr node) {
185 return node && (node / size() * size()) == current_epoch_;
186 }
187
188 void removeNode(uptr node) {
189 uptr idx = nodeToIndex(node);
190 CHECK(!available_nodes_.getBit(idx));
191 CHECK(recycled_nodes_.setBit(idx));
192 g_.removeEdgesFrom(idx);
193 }
194
195 void ensureCurrentEpoch(DeadlockDetectorTLS<BV> *dtls) {
196 dtls->ensureCurrentEpoch(current_epoch_);
197 }
198
199 // Returns true if there is a cycle in the graph after this lock event.
200 // Ideally should be called before the lock is acquired so that we can
201 // report a deadlock before a real deadlock happens.
202 bool onLockBefore(DeadlockDetectorTLS<BV> *dtls, uptr cur_node) {
203 ensureCurrentEpoch(dtls);
204 uptr cur_idx = nodeToIndex(cur_node);
205 return g_.isReachable(cur_idx, dtls->getLocks(current_epoch_));
206 }
207
208 u32 findLockContext(DeadlockDetectorTLS<BV> *dtls, uptr node) {
209 return dtls->findLockContext(nodeToIndex(node));
210 }
211
212 // Add cur_node to the set of locks held currently by dtls.
213 void onLockAfter(DeadlockDetectorTLS<BV> *dtls, uptr cur_node, u32 stk = 0) {
214 ensureCurrentEpoch(dtls);
215 uptr cur_idx = nodeToIndex(cur_node);
216 dtls->addLock(cur_idx, current_epoch_, stk);
217 }
218
219 // Experimental *racy* fast path function.
220 // Returns true if all edges from the currently held locks to cur_node exist.
221 bool hasAllEdges(DeadlockDetectorTLS<BV> *dtls, uptr cur_node) {
222 uptr local_epoch = dtls->getEpoch();
223 // Read from current_epoch_ is racy.
224 if (cur_node && local_epoch == current_epoch_ &&
225 local_epoch == nodeToEpoch(cur_node)) {
226 uptr cur_idx = nodeToIndexUnchecked(cur_node);
227 for (uptr i = 0, n = dtls->getNumLocks(); i < n; i++) {
228 if (!g_.hasEdge(dtls->getLock(i), cur_idx))
229 return false;
230 }
231 return true;
232 }
233 return false;
234 }
235
236 // Adds edges from currently held locks to cur_node,
237 // returns the number of added edges, and puts the sources of added edges
238 // into added_edges[].
239 // Should be called before onLockAfter.
240 uptr addEdges(DeadlockDetectorTLS<BV> *dtls, uptr cur_node, u32 stk,
241 int unique_tid) {
242 ensureCurrentEpoch(dtls);
243 uptr cur_idx = nodeToIndex(cur_node);
244 uptr added_edges[40];
245 uptr n_added_edges = g_.addEdges(dtls->getLocks(current_epoch_), cur_idx,
246 added_edges, ARRAY_SIZE(added_edges));
247 for (uptr i = 0; i < n_added_edges; i++) {
248 if (n_edges_ < ARRAY_SIZE(edges_)) {
249 Edge e = {(u16)added_edges[i], (u16)cur_idx,
250 dtls->findLockContext(added_edges[i]), stk,
251 unique_tid};
252 edges_[n_edges_++] = e;
253 }
254 }
255 return n_added_edges;
256 }
257
258 bool findEdge(uptr from_node, uptr to_node, u32 *stk_from, u32 *stk_to,
259 int *unique_tid) {
260 uptr from_idx = nodeToIndex(from_node);
261 uptr to_idx = nodeToIndex(to_node);
262 for (uptr i = 0; i < n_edges_; i++) {
263 if (edges_[i].from == from_idx && edges_[i].to == to_idx) {
264 *stk_from = edges_[i].stk_from;
265 *stk_to = edges_[i].stk_to;
266 *unique_tid = edges_[i].unique_tid;
267 return true;
268 }
269 }
270 return false;
271 }
272
273 // Test-only function. Handles the before/after lock events,
274 // returns true if there is a cycle.
275 bool onLock(DeadlockDetectorTLS<BV> *dtls, uptr cur_node, u32 stk = 0) {
276 ensureCurrentEpoch(dtls);
277 bool is_reachable = !isHeld(dtls, cur_node) && onLockBefore(dtls, cur_node);
278 addEdges(dtls, cur_node, stk, 0);
279 onLockAfter(dtls, cur_node, stk);
280 return is_reachable;
281 }
282
283 // Handles the try_lock event, returns false.
284 // When a try_lock event happens (i.e. a try_lock call succeeds) we need
285 // to add this lock to the currently held locks, but we should not try to
286 // change the lock graph or to detect a cycle. We may want to investigate
287 // whether a more aggressive strategy is possible for try_lock.
288 bool onTryLock(DeadlockDetectorTLS<BV> *dtls, uptr cur_node, u32 stk = 0) {
289 ensureCurrentEpoch(dtls);
290 uptr cur_idx = nodeToIndex(cur_node);
291 dtls->addLock(cur_idx, current_epoch_, stk);
292 return false;
293 }
294
295 // 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.
297 // This operation is thread-safe as it only touches the dtls.
298 bool onFirstLock(DeadlockDetectorTLS<BV> *dtls, uptr node, u32 stk = 0) {
299 if (!dtls->empty()) return false;
300 if (dtls->getEpoch() && dtls->getEpoch() == nodeToEpoch(node)) {
301 dtls->addLock(nodeToIndexUnchecked(node), nodeToEpoch(node), stk);
302 return true;
303 }
304 return false;
305 }
306
307 // Finds a path between the lock 'cur_node' (currently not held in dtls)
308 // and some currently held lock, returns the length of the path
309 // or 0 on failure.
310 uptr findPathToLock(DeadlockDetectorTLS<BV> *dtls, uptr cur_node, uptr *path,
311 uptr path_size) {
312 tmp_bv_.copyFrom(dtls->getLocks(current_epoch_));
313 uptr idx = nodeToIndex(cur_node);
314 CHECK(!tmp_bv_.getBit(idx));
315 uptr res = g_.findShortestPath(idx, tmp_bv_, path, path_size);
316 for (uptr i = 0; i < res; i++)
317 path[i] = indexToNode(path[i]);
318 if (res)
319 CHECK_EQ(path[0], cur_node);
320 return res;
321 }
322
323 // Handle the unlock event.
324 // This operation is thread-safe as it only touches the dtls.
325 void onUnlock(DeadlockDetectorTLS<BV> *dtls, uptr node) {
326 if (dtls->getEpoch() == nodeToEpoch(node))
327 dtls->removeLock(nodeToIndexUnchecked(node));
328 }
329
330 // Tries to handle the lock event w/o writing to global state.
331 // Returns true on success.
332 // This operation is thread-safe as it only touches the dtls
333 // (modulo racy nature of hasAllEdges).
334 bool onLockFast(DeadlockDetectorTLS<BV> *dtls, uptr node, u32 stk = 0) {
335 if (hasAllEdges(dtls, node)) {
336 dtls->addLock(nodeToIndexUnchecked(node), nodeToEpoch(node), stk);
337 return true;
338 }
339 return false;
340 }
341
342 bool isHeld(DeadlockDetectorTLS<BV> *dtls, uptr node) const {
343 return dtls->getLocks(current_epoch_).getBit(nodeToIndex(node));
344 }
345
346 uptr testOnlyGetEpoch() const { return current_epoch_; }
347 bool testOnlyHasEdge(uptr l1, uptr l2) {
348 return g_.hasEdge(nodeToIndex(l1), nodeToIndex(l2));
349 }
350 // idx1 and idx2 are raw indices to g_, not lock IDs.
351 bool testOnlyHasEdgeRaw(uptr idx1, uptr idx2) {
352 return g_.hasEdge(idx1, idx2);
353 }
354
355 void Print() {
356 for (uptr from = 0; from < size(); from++)
357 for (uptr to = 0; to < size(); to++)
358 if (g_.hasEdge(from, to))
359 Printf(" %zx => %zx\n", from, to);
360 }
361
362 private:
363 void check_idx(uptr idx) const { CHECK_LT(idx, size()); }
364
365 void check_node(uptr node) const {
366 CHECK_GE(node, size());
367 CHECK_EQ(current_epoch_, nodeToEpoch(node));
368 }
369
370 uptr indexToNode(uptr idx) const {
371 check_idx(idx);
372 return idx + current_epoch_;
373 }
374
375 uptr nodeToIndexUnchecked(uptr node) const { return node % size(); }
376
377 uptr nodeToIndex(uptr node) const {
378 check_node(node);
379 return nodeToIndexUnchecked(node);
380 }
381
382 uptr nodeToEpoch(uptr node) const { return node / size() * size(); }
383
384 uptr getAvailableNode(uptr data) {
385 uptr idx = available_nodes_.getAndClearFirstOne();
386 data_[idx] = data;
387 return indexToNode(idx);
388 }
389
390 struct Edge {
391 u16 from;
392 u16 to;
393 u32 stk_from;
394 u32 stk_to;
395 int unique_tid;
396 };
397
398 uptr current_epoch_;
399 BV available_nodes_;
400 BV recycled_nodes_;
401 BV tmp_bv_;
402 BVGraph<BV> g_;
403 uptr data_[BV::kSize];
404 Edge edges_[BV::kSize * 32];
405 uptr n_edges_;
406};
407
408} // namespace __sanitizer
409
410#endif // SANITIZER_DEADLOCK_DETECTOR_H
lib/tsan/sanitizer_common/sanitizer_deadlock_detector1.cpp created+194
...@@ -0,0 +1,194 @@
1//===-- sanitizer_deadlock_detector1.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// Deadlock detector implementation based on NxN adjacency bit matrix.
10//
11//===----------------------------------------------------------------------===//
12
13#include "sanitizer_deadlock_detector_interface.h"
14#include "sanitizer_deadlock_detector.h"
15#include "sanitizer_allocator_internal.h"
16#include "sanitizer_placement_new.h"
17#include "sanitizer_mutex.h"
18
19#if SANITIZER_DEADLOCK_DETECTOR_VERSION == 1
20
21namespace __sanitizer {
22
23typedef TwoLevelBitVector<> DDBV; // DeadlockDetector's bit vector.
24
25struct DDPhysicalThread {
26};
27
28struct DDLogicalThread {
29 u64 ctx;
30 DeadlockDetectorTLS<DDBV> dd;
31 DDReport rep;
32 bool report_pending;
33};
34
35struct DD : public DDetector {
36 SpinMutex mtx;
37 DeadlockDetector<DDBV> dd;
38 DDFlags flags;
39
40 explicit DD(const DDFlags *flags);
41
42 DDPhysicalThread *CreatePhysicalThread() override;
43 void DestroyPhysicalThread(DDPhysicalThread *pt) override;
44
45 DDLogicalThread *CreateLogicalThread(u64 ctx) override;
46 void DestroyLogicalThread(DDLogicalThread *lt) override;
47
48 void MutexInit(DDCallback *cb, DDMutex *m) override;
49 void MutexBeforeLock(DDCallback *cb, DDMutex *m, bool wlock) override;
50 void MutexAfterLock(DDCallback *cb, DDMutex *m, bool wlock,
51 bool trylock) override;
52 void MutexBeforeUnlock(DDCallback *cb, DDMutex *m, bool wlock) override;
53 void MutexDestroy(DDCallback *cb, DDMutex *m) override;
54
55 DDReport *GetReport(DDCallback *cb) override;
56
57 void MutexEnsureID(DDLogicalThread *lt, DDMutex *m);
58 void ReportDeadlock(DDCallback *cb, DDMutex *m);
59};
60
61DDetector *DDetector::Create(const DDFlags *flags) {
62 (void)flags;
63 void *mem = MmapOrDie(sizeof(DD), "deadlock detector");
64 return new(mem) DD(flags);
65}
66
67DD::DD(const DDFlags *flags)
68 : flags(*flags) {
69 dd.clear();
70}
71
72DDPhysicalThread* DD::CreatePhysicalThread() {
73 return nullptr;
74}
75
76void DD::DestroyPhysicalThread(DDPhysicalThread *pt) {
77}
78
79DDLogicalThread* DD::CreateLogicalThread(u64 ctx) {
80 DDLogicalThread *lt = (DDLogicalThread*)InternalAlloc(sizeof(*lt));
81 lt->ctx = ctx;
82 lt->dd.clear();
83 lt->report_pending = false;
84 return lt;
85}
86
87void DD::DestroyLogicalThread(DDLogicalThread *lt) {
88 lt->~DDLogicalThread();
89 InternalFree(lt);
90}
91
92void DD::MutexInit(DDCallback *cb, DDMutex *m) {
93 m->id = 0;
94 m->stk = cb->Unwind();
95}
96
97void DD::MutexEnsureID(DDLogicalThread *lt, DDMutex *m) {
98 if (!dd.nodeBelongsToCurrentEpoch(m->id))
99 m->id = dd.newNode(reinterpret_cast<uptr>(m));
100 dd.ensureCurrentEpoch(&lt->dd);
101}
102
103void DD::MutexBeforeLock(DDCallback *cb,
104 DDMutex *m, bool wlock) {
105 DDLogicalThread *lt = cb->lt;
106 if (lt->dd.empty()) return; // This will be the first lock held by lt.
107 if (dd.hasAllEdges(&lt->dd, m->id)) return; // We already have all edges.
108 SpinMutexLock lk(&mtx);
109 MutexEnsureID(lt, m);
110 if (dd.isHeld(&lt->dd, m->id))
111 return; // FIXME: allow this only for recursive locks.
112 if (dd.onLockBefore(&lt->dd, m->id)) {
113 // Actually add this edge now so that we have all the stack traces.
114 dd.addEdges(&lt->dd, m->id, cb->Unwind(), cb->UniqueTid());
115 ReportDeadlock(cb, m);
116 }
117}
118
119void DD::ReportDeadlock(DDCallback *cb, DDMutex *m) {
120 DDLogicalThread *lt = cb->lt;
121 uptr path[20];
122 uptr len = dd.findPathToLock(&lt->dd, m->id, path, ARRAY_SIZE(path));
123 if (len == 0U) {
124 // A cycle of 20+ locks? Well, that's a bit odd...
125 Printf("WARNING: too long mutex cycle found\n");
126 return;
127 }
128 CHECK_EQ(m->id, path[0]);
129 lt->report_pending = true;
130 len = Min<uptr>(len, DDReport::kMaxLoopSize);
131 DDReport *rep = &lt->rep;
132 rep->n = len;
133 for (uptr i = 0; i < len; i++) {
134 uptr from = path[i];
135 uptr to = path[(i + 1) % len];
136 DDMutex *m0 = (DDMutex*)dd.getData(from);
137 DDMutex *m1 = (DDMutex*)dd.getData(to);
138
139 u32 stk_from = -1U, stk_to = -1U;
140 int unique_tid = 0;
141 dd.findEdge(from, to, &stk_from, &stk_to, &unique_tid);
142 // Printf("Edge: %zd=>%zd: %u/%u T%d\n", from, to, stk_from, stk_to,
143 // unique_tid);
144 rep->loop[i].thr_ctx = unique_tid;
145 rep->loop[i].mtx_ctx0 = m0->ctx;
146 rep->loop[i].mtx_ctx1 = m1->ctx;
147 rep->loop[i].stk[0] = stk_to;
148 rep->loop[i].stk[1] = stk_from;
149 }
150}
151
152void DD::MutexAfterLock(DDCallback *cb, DDMutex *m, bool wlock, bool trylock) {
153 DDLogicalThread *lt = cb->lt;
154 u32 stk = 0;
155 if (flags.second_deadlock_stack)
156 stk = cb->Unwind();
157 // Printf("T%p MutexLock: %zx stk %u\n", lt, m->id, stk);
158 if (dd.onFirstLock(&lt->dd, m->id, stk))
159 return;
160 if (dd.onLockFast(&lt->dd, m->id, stk))
161 return;
162
163 SpinMutexLock lk(&mtx);
164 MutexEnsureID(lt, m);
165 if (wlock) // Only a recursive rlock may be held.
166 CHECK(!dd.isHeld(&lt->dd, m->id));
167 if (!trylock)
168 dd.addEdges(&lt->dd, m->id, stk ? stk : cb->Unwind(), cb->UniqueTid());
169 dd.onLockAfter(&lt->dd, m->id, stk);
170}
171
172void DD::MutexBeforeUnlock(DDCallback *cb, DDMutex *m, bool wlock) {
173 // Printf("T%p MutexUnLock: %zx\n", cb->lt, m->id);
174 dd.onUnlock(&cb->lt->dd, m->id);
175}
176
177void DD::MutexDestroy(DDCallback *cb,
178 DDMutex *m) {
179 if (!m->id) return;
180 SpinMutexLock lk(&mtx);
181 if (dd.nodeBelongsToCurrentEpoch(m->id))
182 dd.removeNode(m->id);
183 m->id = 0;
184}
185
186DDReport *DD::GetReport(DDCallback *cb) {
187 if (!cb->lt->report_pending)
188 return nullptr;
189 cb->lt->report_pending = false;
190 return &cb->lt->rep;
191}
192
193} // namespace __sanitizer
194#endif // #if SANITIZER_DEADLOCK_DETECTOR_VERSION == 1
lib/tsan/sanitizer_common/sanitizer_deadlock_detector2.cpp created+423
...@@ -0,0 +1,423 @@
1//===-- sanitizer_deadlock_detector2.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// Deadlock detector implementation based on adjacency lists.
10//
11//===----------------------------------------------------------------------===//
12
13#include "sanitizer_deadlock_detector_interface.h"
14#include "sanitizer_common.h"
15#include "sanitizer_allocator_internal.h"
16#include "sanitizer_placement_new.h"
17#include "sanitizer_mutex.h"
18
19#if SANITIZER_DEADLOCK_DETECTOR_VERSION == 2
20
21namespace __sanitizer {
22
23const int kMaxNesting = 64;
24const u32 kNoId = -1;
25const u32 kEndId = -2;
26const int kMaxLink = 8;
27const int kL1Size = 1024;
28const int kL2Size = 1024;
29const int kMaxMutex = kL1Size * kL2Size;
30
31struct Id {
32 u32 id;
33 u32 seq;
34
35 explicit Id(u32 id = 0, u32 seq = 0)
36 : id(id)
37 , seq(seq) {
38 }
39};
40
41struct Link {
42 u32 id;
43 u32 seq;
44 u32 tid;
45 u32 stk0;
46 u32 stk1;
47
48 explicit Link(u32 id = 0, u32 seq = 0, u32 tid = 0, u32 s0 = 0, u32 s1 = 0)
49 : id(id)
50 , seq(seq)
51 , tid(tid)
52 , stk0(s0)
53 , stk1(s1) {
54 }
55};
56
57struct DDPhysicalThread {
58 DDReport rep;
59 bool report_pending;
60 bool visited[kMaxMutex];
61 Link pending[kMaxMutex];
62 Link path[kMaxMutex];
63};
64
65struct ThreadMutex {
66 u32 id;
67 u32 stk;
68};
69
70struct DDLogicalThread {
71 u64 ctx;
72 ThreadMutex locked[kMaxNesting];
73 int nlocked;
74};
75
76struct Mutex {
77 StaticSpinMutex mtx;
78 u32 seq;
79 int nlink;
80 Link link[kMaxLink];
81};
82
83struct DD : public DDetector {
84 explicit DD(const DDFlags *flags);
85
86 DDPhysicalThread* CreatePhysicalThread();
87 void DestroyPhysicalThread(DDPhysicalThread *pt);
88
89 DDLogicalThread* CreateLogicalThread(u64 ctx);
90 void DestroyLogicalThread(DDLogicalThread *lt);
91
92 void MutexInit(DDCallback *cb, DDMutex *m);
93 void MutexBeforeLock(DDCallback *cb, DDMutex *m, bool wlock);
94 void MutexAfterLock(DDCallback *cb, DDMutex *m, bool wlock,
95 bool trylock);
96 void MutexBeforeUnlock(DDCallback *cb, DDMutex *m, bool wlock);
97 void MutexDestroy(DDCallback *cb, DDMutex *m);
98
99 DDReport *GetReport(DDCallback *cb);
100
101 void CycleCheck(DDPhysicalThread *pt, DDLogicalThread *lt, DDMutex *mtx);
102 void Report(DDPhysicalThread *pt, DDLogicalThread *lt, int npath);
103 u32 allocateId(DDCallback *cb);
104 Mutex *getMutex(u32 id);
105 u32 getMutexId(Mutex *m);
106
107 DDFlags flags;
108
109 Mutex* mutex[kL1Size];
110
111 SpinMutex mtx;
112 InternalMmapVector<u32> free_id;
113 int id_gen = 0;
114};
115
116DDetector *DDetector::Create(const DDFlags *flags) {
117 (void)flags;
118 void *mem = MmapOrDie(sizeof(DD), "deadlock detector");
119 return new(mem) DD(flags);
120}
121
122DD::DD(const DDFlags *flags) : flags(*flags) { free_id.reserve(1024); }
123
124DDPhysicalThread* DD::CreatePhysicalThread() {
125 DDPhysicalThread *pt = (DDPhysicalThread*)MmapOrDie(sizeof(DDPhysicalThread),
126 "deadlock detector (physical thread)");
127 return pt;
128}
129
130void DD::DestroyPhysicalThread(DDPhysicalThread *pt) {
131 pt->~DDPhysicalThread();
132 UnmapOrDie(pt, sizeof(DDPhysicalThread));
133}
134
135DDLogicalThread* DD::CreateLogicalThread(u64 ctx) {
136 DDLogicalThread *lt = (DDLogicalThread*)InternalAlloc(
137 sizeof(DDLogicalThread));
138 lt->ctx = ctx;
139 lt->nlocked = 0;
140 return lt;
141}
142
143void DD::DestroyLogicalThread(DDLogicalThread *lt) {
144 lt->~DDLogicalThread();
145 InternalFree(lt);
146}
147
148void DD::MutexInit(DDCallback *cb, DDMutex *m) {
149 VPrintf(2, "#%llu: DD::MutexInit(%p)\n", cb->lt->ctx, m);
150 m->id = kNoId;
151 m->recursion = 0;
152 atomic_store(&m->owner, 0, memory_order_relaxed);
153}
154
155Mutex *DD::getMutex(u32 id) {
156 return &mutex[id / kL2Size][id % kL2Size];
157}
158
159u32 DD::getMutexId(Mutex *m) {
160 for (int i = 0; i < kL1Size; i++) {
161 Mutex *tab = mutex[i];
162 if (tab == 0)
163 break;
164 if (m >= tab && m < tab + kL2Size)
165 return i * kL2Size + (m - tab);
166 }
167 return -1;
168}
169
170u32 DD::allocateId(DDCallback *cb) {
171 u32 id = -1;
172 SpinMutexLock l(&mtx);
173 if (free_id.size() > 0) {
174 id = free_id.back();
175 free_id.pop_back();
176 } else {
177 CHECK_LT(id_gen, kMaxMutex);
178 if ((id_gen % kL2Size) == 0) {
179 mutex[id_gen / kL2Size] = (Mutex*)MmapOrDie(kL2Size * sizeof(Mutex),
180 "deadlock detector (mutex table)");
181 }
182 id = id_gen++;
183 }
184 CHECK_LE(id, kMaxMutex);
185 VPrintf(3, "#%llu: DD::allocateId assign id %d\n", cb->lt->ctx, id);
186 return id;
187}
188
189void DD::MutexBeforeLock(DDCallback *cb, DDMutex *m, bool wlock) {
190 VPrintf(2, "#%llu: DD::MutexBeforeLock(%p, wlock=%d) nlocked=%d\n",
191 cb->lt->ctx, m, wlock, cb->lt->nlocked);
192 DDPhysicalThread *pt = cb->pt;
193 DDLogicalThread *lt = cb->lt;
194
195 uptr owner = atomic_load(&m->owner, memory_order_relaxed);
196 if (owner == (uptr)cb->lt) {
197 VPrintf(3, "#%llu: DD::MutexBeforeLock recursive\n",
198 cb->lt->ctx);
199 return;
200 }
201
202 CHECK_LE(lt->nlocked, kMaxNesting);
203
204 // FIXME(dvyukov): don't allocate id if lt->nlocked == 0?
205 if (m->id == kNoId)
206 m->id = allocateId(cb);
207
208 ThreadMutex *tm = &lt->locked[lt->nlocked++];
209 tm->id = m->id;
210 if (flags.second_deadlock_stack)
211 tm->stk = cb->Unwind();
212 if (lt->nlocked == 1) {
213 VPrintf(3, "#%llu: DD::MutexBeforeLock first mutex\n",
214 cb->lt->ctx);
215 return;
216 }
217
218 bool added = false;
219 Mutex *mtx = getMutex(m->id);
220 for (int i = 0; i < lt->nlocked - 1; i++) {
221 u32 id1 = lt->locked[i].id;
222 u32 stk1 = lt->locked[i].stk;
223 Mutex *mtx1 = getMutex(id1);
224 SpinMutexLock l(&mtx1->mtx);
225 if (mtx1->nlink == kMaxLink) {
226 // FIXME(dvyukov): check stale links
227 continue;
228 }
229 int li = 0;
230 for (; li < mtx1->nlink; li++) {
231 Link *link = &mtx1->link[li];
232 if (link->id == m->id) {
233 if (link->seq != mtx->seq) {
234 link->seq = mtx->seq;
235 link->tid = lt->ctx;
236 link->stk0 = stk1;
237 link->stk1 = cb->Unwind();
238 added = true;
239 VPrintf(3, "#%llu: DD::MutexBeforeLock added %d->%d link\n",
240 cb->lt->ctx, getMutexId(mtx1), m->id);
241 }
242 break;
243 }
244 }
245 if (li == mtx1->nlink) {
246 // FIXME(dvyukov): check stale links
247 Link *link = &mtx1->link[mtx1->nlink++];
248 link->id = m->id;
249 link->seq = mtx->seq;
250 link->tid = lt->ctx;
251 link->stk0 = stk1;
252 link->stk1 = cb->Unwind();
253 added = true;
254 VPrintf(3, "#%llu: DD::MutexBeforeLock added %d->%d link\n",
255 cb->lt->ctx, getMutexId(mtx1), m->id);
256 }
257 }
258
259 if (!added || mtx->nlink == 0) {
260 VPrintf(3, "#%llu: DD::MutexBeforeLock don't check\n",
261 cb->lt->ctx);
262 return;
263 }
264
265 CycleCheck(pt, lt, m);
266}
267
268void DD::MutexAfterLock(DDCallback *cb, DDMutex *m, bool wlock,
269 bool trylock) {
270 VPrintf(2, "#%llu: DD::MutexAfterLock(%p, wlock=%d, try=%d) nlocked=%d\n",
271 cb->lt->ctx, m, wlock, trylock, cb->lt->nlocked);
272 DDLogicalThread *lt = cb->lt;
273
274 uptr owner = atomic_load(&m->owner, memory_order_relaxed);
275 if (owner == (uptr)cb->lt) {
276 VPrintf(3, "#%llu: DD::MutexAfterLock recursive\n", cb->lt->ctx);
277 CHECK(wlock);
278 m->recursion++;
279 return;
280 }
281 CHECK_EQ(owner, 0);
282 if (wlock) {
283 VPrintf(3, "#%llu: DD::MutexAfterLock set owner\n", cb->lt->ctx);
284 CHECK_EQ(m->recursion, 0);
285 m->recursion = 1;
286 atomic_store(&m->owner, (uptr)cb->lt, memory_order_relaxed);
287 }
288
289 if (!trylock)
290 return;
291
292 CHECK_LE(lt->nlocked, kMaxNesting);
293 if (m->id == kNoId)
294 m->id = allocateId(cb);
295 ThreadMutex *tm = &lt->locked[lt->nlocked++];
296 tm->id = m->id;
297 if (flags.second_deadlock_stack)
298 tm->stk = cb->Unwind();
299}
300
301void DD::MutexBeforeUnlock(DDCallback *cb, DDMutex *m, bool wlock) {
302 VPrintf(2, "#%llu: DD::MutexBeforeUnlock(%p, wlock=%d) nlocked=%d\n",
303 cb->lt->ctx, m, wlock, cb->lt->nlocked);
304 DDLogicalThread *lt = cb->lt;
305
306 uptr owner = atomic_load(&m->owner, memory_order_relaxed);
307 if (owner == (uptr)cb->lt) {
308 VPrintf(3, "#%llu: DD::MutexBeforeUnlock recursive\n", cb->lt->ctx);
309 if (--m->recursion > 0)
310 return;
311 VPrintf(3, "#%llu: DD::MutexBeforeUnlock reset owner\n", cb->lt->ctx);
312 atomic_store(&m->owner, 0, memory_order_relaxed);
313 }
314 CHECK_NE(m->id, kNoId);
315 int last = lt->nlocked - 1;
316 for (int i = last; i >= 0; i--) {
317 if (cb->lt->locked[i].id == m->id) {
318 lt->locked[i] = lt->locked[last];
319 lt->nlocked--;
320 break;
321 }
322 }
323}
324
325void DD::MutexDestroy(DDCallback *cb, DDMutex *m) {
326 VPrintf(2, "#%llu: DD::MutexDestroy(%p)\n",
327 cb->lt->ctx, m);
328 DDLogicalThread *lt = cb->lt;
329
330 if (m->id == kNoId)
331 return;
332
333 // Remove the mutex from lt->locked if there.
334 int last = lt->nlocked - 1;
335 for (int i = last; i >= 0; i--) {
336 if (lt->locked[i].id == m->id) {
337 lt->locked[i] = lt->locked[last];
338 lt->nlocked--;
339 break;
340 }
341 }
342
343 // Clear and invalidate the mutex descriptor.
344 {
345 Mutex *mtx = getMutex(m->id);
346 SpinMutexLock l(&mtx->mtx);
347 mtx->seq++;
348 mtx->nlink = 0;
349 }
350
351 // Return id to cache.
352 {
353 SpinMutexLock l(&mtx);
354 free_id.push_back(m->id);
355 }
356}
357
358void DD::CycleCheck(DDPhysicalThread *pt, DDLogicalThread *lt,
359 DDMutex *m) {
360 internal_memset(pt->visited, 0, sizeof(pt->visited));
361 int npath = 0;
362 int npending = 0;
363 {
364 Mutex *mtx = getMutex(m->id);
365 SpinMutexLock l(&mtx->mtx);
366 for (int li = 0; li < mtx->nlink; li++)
367 pt->pending[npending++] = mtx->link[li];
368 }
369 while (npending > 0) {
370 Link link = pt->pending[--npending];
371 if (link.id == kEndId) {
372 npath--;
373 continue;
374 }
375 if (pt->visited[link.id])
376 continue;
377 Mutex *mtx1 = getMutex(link.id);
378 SpinMutexLock l(&mtx1->mtx);
379 if (mtx1->seq != link.seq)
380 continue;
381 pt->visited[link.id] = true;
382 if (mtx1->nlink == 0)
383 continue;
384 pt->path[npath++] = link;
385 pt->pending[npending++] = Link(kEndId);
386 if (link.id == m->id)
387 return Report(pt, lt, npath); // Bingo!
388 for (int li = 0; li < mtx1->nlink; li++) {
389 Link *link1 = &mtx1->link[li];
390 // Mutex *mtx2 = getMutex(link->id);
391 // FIXME(dvyukov): fast seq check
392 // FIXME(dvyukov): fast nlink != 0 check
393 // FIXME(dvyukov): fast pending check?
394 // FIXME(dvyukov): npending can be larger than kMaxMutex
395 pt->pending[npending++] = *link1;
396 }
397 }
398}
399
400void DD::Report(DDPhysicalThread *pt, DDLogicalThread *lt, int npath) {
401 DDReport *rep = &pt->rep;
402 rep->n = npath;
403 for (int i = 0; i < npath; i++) {
404 Link *link = &pt->path[i];
405 Link *link0 = &pt->path[i ? i - 1 : npath - 1];
406 rep->loop[i].thr_ctx = link->tid;
407 rep->loop[i].mtx_ctx0 = link0->id;
408 rep->loop[i].mtx_ctx1 = link->id;
409 rep->loop[i].stk[0] = flags.second_deadlock_stack ? link->stk0 : 0;
410 rep->loop[i].stk[1] = link->stk1;
411 }
412 pt->report_pending = true;
413}
414
415DDReport *DD::GetReport(DDCallback *cb) {
416 if (!cb->pt->report_pending)
417 return 0;
418 cb->pt->report_pending = false;
419 return &cb->pt->rep;
420}
421
422} // namespace __sanitizer
423#endif // #if SANITIZER_DEADLOCK_DETECTOR_VERSION == 2
lib/tsan/sanitizer_common/sanitizer_deadlock_detector_interface.h created+92
...@@ -0,0 +1,92 @@
1//===-- sanitizer_deadlock_detector_interface.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.
10// Abstract deadlock detector interface.
11// FIXME: this is work in progress, nothing really works yet.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef SANITIZER_DEADLOCK_DETECTOR_INTERFACE_H
16#define SANITIZER_DEADLOCK_DETECTOR_INTERFACE_H
17
18#ifndef SANITIZER_DEADLOCK_DETECTOR_VERSION
19# define SANITIZER_DEADLOCK_DETECTOR_VERSION 1
20#endif
21
22#include "sanitizer_internal_defs.h"
23#include "sanitizer_atomic.h"
24
25namespace __sanitizer {
26
27// dd - deadlock detector.
28// lt - logical (user) thread.
29// pt - physical (OS) thread.
30
31struct DDPhysicalThread;
32struct DDLogicalThread;
33
34struct DDMutex {
35#if SANITIZER_DEADLOCK_DETECTOR_VERSION == 1
36 uptr id;
37 u32 stk; // creation stack
38#elif SANITIZER_DEADLOCK_DETECTOR_VERSION == 2
39 u32 id;
40 u32 recursion;
41 atomic_uintptr_t owner;
42#else
43# error "BAD SANITIZER_DEADLOCK_DETECTOR_VERSION"
44#endif
45 u64 ctx;
46};
47
48struct DDFlags {
49 bool second_deadlock_stack;
50};
51
52struct DDReport {
53 enum { kMaxLoopSize = 20 };
54 int n; // number of entries in loop
55 struct {
56 u64 thr_ctx; // user thread context
57 u64 mtx_ctx0; // user mutex context, start of the edge
58 u64 mtx_ctx1; // user mutex context, end of the edge
59 u32 stk[2]; // stack ids for the edge
60 } loop[kMaxLoopSize];
61};
62
63struct DDCallback {
64 DDPhysicalThread *pt;
65 DDLogicalThread *lt;
66
67 virtual u32 Unwind() { return 0; }
68 virtual int UniqueTid() { return 0; }
69};
70
71struct DDetector {
72 static DDetector *Create(const DDFlags *flags);
73
74 virtual DDPhysicalThread* CreatePhysicalThread() { return nullptr; }
75 virtual void DestroyPhysicalThread(DDPhysicalThread *pt) {}
76
77 virtual DDLogicalThread* CreateLogicalThread(u64 ctx) { return nullptr; }
78 virtual void DestroyLogicalThread(DDLogicalThread *lt) {}
79
80 virtual void MutexInit(DDCallback *cb, DDMutex *m) {}
81 virtual void MutexBeforeLock(DDCallback *cb, DDMutex *m, bool wlock) {}
82 virtual void MutexAfterLock(DDCallback *cb, DDMutex *m, bool wlock,
83 bool trylock) {}
84 virtual void MutexBeforeUnlock(DDCallback *cb, DDMutex *m, bool wlock) {}
85 virtual void MutexDestroy(DDCallback *cb, DDMutex *m) {}
86
87 virtual DDReport *GetReport(DDCallback *cb) { return nullptr; }
88};
89
90} // namespace __sanitizer
91
92#endif // SANITIZER_DEADLOCK_DETECTOR_INTERFACE_H
lib/tsan/sanitizer_common/sanitizer_errno.cpp created+34
...@@ -0,0 +1,34 @@
1//===-- sanitizer_errno.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 sanitizers run-time libraries.
10//
11// Defines errno to avoid including errno.h and its dependencies into other
12// files (e.g. interceptors are not supposed to include any system headers).
13//
14//===----------------------------------------------------------------------===//
15
16#include "sanitizer_errno_codes.h"
17#include "sanitizer_internal_defs.h"
18
19#include <errno.h>
20
21namespace __sanitizer {
22
23COMPILER_CHECK(errno_ENOMEM == ENOMEM);
24COMPILER_CHECK(errno_EBUSY == EBUSY);
25COMPILER_CHECK(errno_EINVAL == EINVAL);
26
27// EOWNERDEAD is not present in some older platforms.
28#if defined(EOWNERDEAD)
29extern const int errno_EOWNERDEAD = EOWNERDEAD;
30#else
31extern const int errno_EOWNERDEAD = -1;
32#endif
33
34} // namespace __sanitizer
lib/tsan/sanitizer_common/sanitizer_errno.h created+39
...@@ -0,0 +1,39 @@
1//===-- sanitizer_errno.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 sanitizers run-time libraries.
10//
11// Defines errno to avoid including errno.h and its dependencies into sensitive
12// files (e.g. interceptors are not supposed to include any system headers).
13// It's ok to use errno.h directly when your file already depend on other system
14// includes though.
15//
16//===----------------------------------------------------------------------===//
17
18#ifndef SANITIZER_ERRNO_H
19#define SANITIZER_ERRNO_H
20
21#include "sanitizer_errno_codes.h"
22#include "sanitizer_platform.h"
23
24#if SANITIZER_FREEBSD || SANITIZER_MAC
25# define __errno_location __error
26#elif SANITIZER_ANDROID || SANITIZER_NETBSD || SANITIZER_OPENBSD || \
27 SANITIZER_RTEMS
28# define __errno_location __errno
29#elif SANITIZER_SOLARIS
30# define __errno_location ___errno
31#elif SANITIZER_WINDOWS
32# define __errno_location _errno
33#endif
34
35extern "C" int *__errno_location();
36
37#define errno (*__errno_location())
38
39#endif // SANITIZER_ERRNO_H
lib/tsan/sanitizer_common/sanitizer_errno_codes.h created+33
...@@ -0,0 +1,33 @@
1//===-- sanitizer_errno_codes.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 sanitizers run-time libraries.
10//
11// Defines errno codes to avoid including errno.h and its dependencies into
12// sensitive files (e.g. interceptors are not supposed to include any system
13// headers).
14// It's ok to use errno.h directly when your file already depend on other system
15// includes though.
16//
17//===----------------------------------------------------------------------===//
18
19#ifndef SANITIZER_ERRNO_CODES_H
20#define SANITIZER_ERRNO_CODES_H
21
22namespace __sanitizer {
23
24#define errno_ENOMEM 12
25#define errno_EBUSY 16
26#define errno_EINVAL 22
27
28// Those might not present or their value differ on different platforms.
29extern const int errno_EOWNERDEAD;
30
31} // namespace __sanitizer
32
33#endif // SANITIZER_ERRNO_CODES_H
lib/tsan/sanitizer_common/sanitizer_file.cpp created+215
...@@ -0,0 +1,215 @@
1//===-- sanitizer_file.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 shared between AddressSanitizer and ThreadSanitizer
10// run-time libraries. It defines filesystem-related interfaces. This
11// is separate from sanitizer_common.cpp so that it's simpler to disable
12// all the filesystem support code for a port that doesn't use it.
13//
14//===---------------------------------------------------------------------===//
15
16#include "sanitizer_platform.h"
17
18#if !SANITIZER_FUCHSIA
19
20#include "sanitizer_common.h"
21#include "sanitizer_file.h"
22
23namespace __sanitizer {
24
25void CatastrophicErrorWrite(const char *buffer, uptr length) {
26 WriteToFile(kStderrFd, buffer, length);
27}
28
29StaticSpinMutex report_file_mu;
30ReportFile report_file = {&report_file_mu, kStderrFd, "", "", 0};
31
32void RawWrite(const char *buffer) {
33 report_file.Write(buffer, internal_strlen(buffer));
34}
35
36void ReportFile::ReopenIfNecessary() {
37 mu->CheckLocked();
38 if (fd == kStdoutFd || fd == kStderrFd) return;
39
40 uptr pid = internal_getpid();
41 // If in tracer, use the parent's file.
42 if (pid == stoptheworld_tracer_pid)
43 pid = stoptheworld_tracer_ppid;
44 if (fd != kInvalidFd) {
45 // If the report file is already opened by the current process,
46 // do nothing. Otherwise the report file was opened by the parent
47 // process, close it now.
48 if (fd_pid == pid)
49 return;
50 else
51 CloseFile(fd);
52 }
53
54 const char *exe_name = GetProcessName();
55 if (common_flags()->log_exe_name && exe_name) {
56 internal_snprintf(full_path, kMaxPathLength, "%s.%s.%zu", path_prefix,
57 exe_name, pid);
58 } else {
59 internal_snprintf(full_path, kMaxPathLength, "%s.%zu", path_prefix, pid);
60 }
61 fd = OpenFile(full_path, WrOnly);
62 if (fd == kInvalidFd) {
63 const char *ErrorMsgPrefix = "ERROR: Can't open file: ";
64 WriteToFile(kStderrFd, ErrorMsgPrefix, internal_strlen(ErrorMsgPrefix));
65 WriteToFile(kStderrFd, full_path, internal_strlen(full_path));
66 Die();
67 }
68 fd_pid = pid;
69}
70
71void ReportFile::SetReportPath(const char *path) {
72 if (!path)
73 return;
74 uptr len = internal_strlen(path);
75 if (len > sizeof(path_prefix) - 100) {
76 Report("ERROR: Path is too long: %c%c%c%c%c%c%c%c...\n",
77 path[0], path[1], path[2], path[3],
78 path[4], path[5], path[6], path[7]);
79 Die();
80 }
81
82 SpinMutexLock l(mu);
83 if (fd != kStdoutFd && fd != kStderrFd && fd != kInvalidFd)
84 CloseFile(fd);
85 fd = kInvalidFd;
86 if (internal_strcmp(path, "stdout") == 0) {
87 fd = kStdoutFd;
88 } else if (internal_strcmp(path, "stderr") == 0) {
89 fd = kStderrFd;
90 } else {
91 internal_snprintf(path_prefix, kMaxPathLength, "%s", path);
92 }
93}
94
95bool ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size,
96 uptr *read_len, uptr max_len, error_t *errno_p) {
97 *buff = nullptr;
98 *buff_size = 0;
99 *read_len = 0;
100 if (!max_len)
101 return true;
102 uptr PageSize = GetPageSizeCached();
103 uptr kMinFileLen = Min(PageSize, max_len);
104
105 // The files we usually open are not seekable, so try different buffer sizes.
106 for (uptr size = kMinFileLen;; size = Min(size * 2, max_len)) {
107 UnmapOrDie(*buff, *buff_size);
108 *buff = (char*)MmapOrDie(size, __func__);
109 *buff_size = size;
110 fd_t fd = OpenFile(file_name, RdOnly, errno_p);
111 if (fd == kInvalidFd) {
112 UnmapOrDie(*buff, *buff_size);
113 return false;
114 }
115 *read_len = 0;
116 // Read up to one page at a time.
117 bool reached_eof = false;
118 while (*read_len < size) {
119 uptr just_read;
120 if (!ReadFromFile(fd, *buff + *read_len, size - *read_len, &just_read,
121 errno_p)) {
122 UnmapOrDie(*buff, *buff_size);
123 CloseFile(fd);
124 return false;
125 }
126 *read_len += just_read;
127 if (just_read == 0 || *read_len == max_len) {
128 reached_eof = true;
129 break;
130 }
131 }
132 CloseFile(fd);
133 if (reached_eof) // We've read the whole file.
134 break;
135 }
136 return true;
137}
138
139bool ReadFileToVector(const char *file_name,
140 InternalMmapVectorNoCtor<char> *buff, uptr max_len,
141 error_t *errno_p) {
142 buff->clear();
143 if (!max_len)
144 return true;
145 uptr PageSize = GetPageSizeCached();
146 fd_t fd = OpenFile(file_name, RdOnly, errno_p);
147 if (fd == kInvalidFd)
148 return false;
149 uptr read_len = 0;
150 while (read_len < max_len) {
151 if (read_len >= buff->size())
152 buff->resize(Min(Max(PageSize, read_len * 2), max_len));
153 CHECK_LT(read_len, buff->size());
154 CHECK_LE(buff->size(), max_len);
155 uptr just_read;
156 if (!ReadFromFile(fd, buff->data() + read_len, buff->size() - read_len,
157 &just_read, errno_p)) {
158 CloseFile(fd);
159 return false;
160 }
161 read_len += just_read;
162 if (!just_read)
163 break;
164 }
165 CloseFile(fd);
166 buff->resize(read_len);
167 return true;
168}
169
170static const char kPathSeparator = SANITIZER_WINDOWS ? ';' : ':';
171
172char *FindPathToBinary(const char *name) {
173 if (FileExists(name)) {
174 return internal_strdup(name);
175 }
176
177 const char *path = GetEnv("PATH");
178 if (!path)
179 return nullptr;
180 uptr name_len = internal_strlen(name);
181 InternalMmapVector<char> buffer(kMaxPathLength);
182 const char *beg = path;
183 while (true) {
184 const char *end = internal_strchrnul(beg, kPathSeparator);
185 uptr prefix_len = end - beg;
186 if (prefix_len + name_len + 2 <= kMaxPathLength) {
187 internal_memcpy(buffer.data(), beg, prefix_len);
188 buffer[prefix_len] = '/';
189 internal_memcpy(&buffer[prefix_len + 1], name, name_len);
190 buffer[prefix_len + 1 + name_len] = '\0';
191 if (FileExists(buffer.data()))
192 return internal_strdup(buffer.data());
193 }
194 if (*end == '\0') break;
195 beg = end + 1;
196 }
197 return nullptr;
198}
199
200} // namespace __sanitizer
201
202using namespace __sanitizer;
203
204extern "C" {
205void __sanitizer_set_report_path(const char *path) {
206 report_file.SetReportPath(path);
207}
208
209void __sanitizer_set_report_fd(void *fd) {
210 report_file.fd = (fd_t)reinterpret_cast<uptr>(fd);
211 report_file.fd_pid = internal_getpid();
212}
213} // extern "C"
214
215#endif // !SANITIZER_FUCHSIA
lib/tsan/sanitizer_common/sanitizer_file.h created+106
...@@ -0,0 +1,106 @@
1//===-- sanitizer_file.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 run-time libraries of sanitizers.
10// It declares filesystem-related interfaces. This is separate from
11// sanitizer_common.h so that it's simpler to disable all the filesystem
12// support code for a port that doesn't use it.
13//
14//===---------------------------------------------------------------------===//
15#ifndef SANITIZER_FILE_H
16#define SANITIZER_FILE_H
17
18#include "sanitizer_interface_internal.h"
19#include "sanitizer_internal_defs.h"
20#include "sanitizer_libc.h"
21#include "sanitizer_mutex.h"
22
23namespace __sanitizer {
24
25struct ReportFile {
26 void Write(const char *buffer, uptr length);
27 bool SupportsColors();
28 void SetReportPath(const char *path);
29
30 // Don't use fields directly. They are only declared public to allow
31 // aggregate initialization.
32
33 // Protects fields below.
34 StaticSpinMutex *mu;
35 // Opened file descriptor. Defaults to stderr. It may be equal to
36 // kInvalidFd, in which case new file will be opened when necessary.
37 fd_t fd;
38 // Path prefix of report file, set via __sanitizer_set_report_path.
39 char path_prefix[kMaxPathLength];
40 // Full path to report, obtained as <path_prefix>.PID
41 char full_path[kMaxPathLength];
42 // PID of the process that opened fd. If a fork() occurs,
43 // the PID of child will be different from fd_pid.
44 uptr fd_pid;
45
46 private:
47 void ReopenIfNecessary();
48};
49extern ReportFile report_file;
50
51enum FileAccessMode {
52 RdOnly,
53 WrOnly,
54 RdWr
55};
56
57// Returns kInvalidFd on error.
58fd_t OpenFile(const char *filename, FileAccessMode mode,
59 error_t *errno_p = nullptr);
60void CloseFile(fd_t);
61
62// Return true on success, false on error.
63bool ReadFromFile(fd_t fd, void *buff, uptr buff_size,
64 uptr *bytes_read = nullptr, error_t *error_p = nullptr);
65bool WriteToFile(fd_t fd, const void *buff, uptr buff_size,
66 uptr *bytes_written = nullptr, error_t *error_p = nullptr);
67
68// Scoped file handle closer.
69struct FileCloser {
70 explicit FileCloser(fd_t fd) : fd(fd) {}
71 ~FileCloser() { CloseFile(fd); }
72 fd_t fd;
73};
74
75bool SupportsColoredOutput(fd_t fd);
76
77// OS
78const char *GetPwd();
79bool FileExists(const char *filename);
80char *FindPathToBinary(const char *name);
81bool IsPathSeparator(const char c);
82bool IsAbsolutePath(const char *path);
83// Starts a subprocess and returs its pid.
84// If *_fd parameters are not kInvalidFd their corresponding input/output
85// streams will be redirect to the file. The files will always be closed
86// in parent process even in case of an error.
87// The child process will close all fds after STDERR_FILENO
88// before passing control to a program.
89pid_t StartSubprocess(const char *filename, const char *const argv[],
90 const char *const envp[], fd_t stdin_fd = kInvalidFd,
91 fd_t stdout_fd = kInvalidFd, fd_t stderr_fd = kInvalidFd);
92// Checks if specified process is still running
93bool IsProcessRunning(pid_t pid);
94// Waits for the process to finish and returns its exit code.
95// Returns -1 in case of an error.
96int WaitForProcess(pid_t pid);
97
98// Maps given file to virtual memory, and returns pointer to it
99// (or NULL if mapping fails). Stores the size of mmaped region
100// in '*buff_size'.
101void *MapFileToMemory(const char *file_name, uptr *buff_size);
102void *MapWritableFileToMemory(void *addr, uptr size, fd_t fd, OFF_T offset);
103
104} // namespace __sanitizer
105
106#endif // SANITIZER_FILE_H
lib/tsan/sanitizer_common/sanitizer_flag_parser.cpp created+191
...@@ -0,0 +1,191 @@
1//===-- sanitizer_flag_parser.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/AddressSanitizer runtime.
10//
11//===----------------------------------------------------------------------===//
12
13#include "sanitizer_flag_parser.h"
14
15#include "sanitizer_common.h"
16#include "sanitizer_libc.h"
17#include "sanitizer_flags.h"
18#include "sanitizer_flag_parser.h"
19
20namespace __sanitizer {
21
22LowLevelAllocator FlagParser::Alloc;
23
24class UnknownFlags {
25 static const int kMaxUnknownFlags = 20;
26 const char *unknown_flags_[kMaxUnknownFlags];
27 int n_unknown_flags_;
28
29 public:
30 void Add(const char *name) {
31 CHECK_LT(n_unknown_flags_, kMaxUnknownFlags);
32 unknown_flags_[n_unknown_flags_++] = name;
33 }
34
35 void Report() {
36 if (!n_unknown_flags_) return;
37 Printf("WARNING: found %d unrecognized flag(s):\n", n_unknown_flags_);
38 for (int i = 0; i < n_unknown_flags_; ++i)
39 Printf(" %s\n", unknown_flags_[i]);
40 n_unknown_flags_ = 0;
41 }
42};
43
44UnknownFlags unknown_flags;
45
46void ReportUnrecognizedFlags() {
47 unknown_flags.Report();
48}
49
50char *FlagParser::ll_strndup(const char *s, uptr n) {
51 uptr len = internal_strnlen(s, n);
52 char *s2 = (char*)Alloc.Allocate(len + 1);
53 internal_memcpy(s2, s, len);
54 s2[len] = 0;
55 return s2;
56}
57
58void FlagParser::PrintFlagDescriptions() {
59 char buffer[128];
60 buffer[sizeof(buffer) - 1] = '\0';
61 Printf("Available flags for %s:\n", SanitizerToolName);
62 for (int i = 0; i < n_flags_; ++i) {
63 bool truncated = !(flags_[i].handler->Format(buffer, sizeof(buffer)));
64 CHECK_EQ(buffer[sizeof(buffer) - 1], '\0');
65 const char *truncation_str = truncated ? " Truncated" : "";
66 Printf("\t%s\n\t\t- %s (Current Value%s: %s)\n", flags_[i].name,
67 flags_[i].desc, truncation_str, buffer);
68 }
69}
70
71void FlagParser::fatal_error(const char *err) {
72 Printf("%s: ERROR: %s\n", SanitizerToolName, err);
73 Die();
74}
75
76bool FlagParser::is_space(char c) {
77 return c == ' ' || c == ',' || c == ':' || c == '\n' || c == '\t' ||
78 c == '\r';
79}
80
81void FlagParser::skip_whitespace() {
82 while (is_space(buf_[pos_])) ++pos_;
83}
84
85void FlagParser::parse_flag(const char *env_option_name) {
86 uptr name_start = pos_;
87 while (buf_[pos_] != 0 && buf_[pos_] != '=' && !is_space(buf_[pos_])) ++pos_;
88 if (buf_[pos_] != '=') {
89 if (env_option_name) {
90 Printf("%s: ERROR: expected '=' in %s\n", SanitizerToolName,
91 env_option_name);
92 Die();
93 } else {
94 fatal_error("expected '='");
95 }
96 }
97 char *name = ll_strndup(buf_ + name_start, pos_ - name_start);
98
99 uptr value_start = ++pos_;
100 char *value;
101 if (buf_[pos_] == '\'' || buf_[pos_] == '"') {
102 char quote = buf_[pos_++];
103 while (buf_[pos_] != 0 && buf_[pos_] != quote) ++pos_;
104 if (buf_[pos_] == 0) fatal_error("unterminated string");
105 value = ll_strndup(buf_ + value_start + 1, pos_ - value_start - 1);
106 ++pos_; // consume the closing quote
107 } else {
108 while (buf_[pos_] != 0 && !is_space(buf_[pos_])) ++pos_;
109 if (buf_[pos_] != 0 && !is_space(buf_[pos_]))
110 fatal_error("expected separator or eol");
111 value = ll_strndup(buf_ + value_start, pos_ - value_start);
112 }
113
114 bool res = run_handler(name, value);
115 if (!res) fatal_error("Flag parsing failed.");
116}
117
118void FlagParser::parse_flags(const char *env_option_name) {
119 while (true) {
120 skip_whitespace();
121 if (buf_[pos_] == 0) break;
122 parse_flag(env_option_name);
123 }
124
125 // Do a sanity check for certain flags.
126 if (common_flags_dont_use.malloc_context_size < 1)
127 common_flags_dont_use.malloc_context_size = 1;
128}
129
130void FlagParser::ParseStringFromEnv(const char *env_name) {
131 const char *env = GetEnv(env_name);
132 VPrintf(1, "%s: %s\n", env_name, env ? env : "<empty>");
133 ParseString(env, env_name);
134}
135
136void FlagParser::ParseString(const char *s, const char *env_option_name) {
137 if (!s) return;
138 // Backup current parser state to allow nested ParseString() calls.
139 const char *old_buf_ = buf_;
140 uptr old_pos_ = pos_;
141 buf_ = s;
142 pos_ = 0;
143
144 parse_flags(env_option_name);
145
146 buf_ = old_buf_;
147 pos_ = old_pos_;
148}
149
150bool FlagParser::ParseFile(const char *path, bool ignore_missing) {
151 static const uptr kMaxIncludeSize = 1 << 15;
152 char *data;
153 uptr data_mapped_size;
154 error_t err;
155 uptr len;
156 if (!ReadFileToBuffer(path, &data, &data_mapped_size, &len,
157 Max(kMaxIncludeSize, GetPageSizeCached()), &err)) {
158 if (ignore_missing)
159 return true;
160 Printf("Failed to read options from '%s': error %d\n", path, err);
161 return false;
162 }
163 ParseString(data, path);
164 UnmapOrDie(data, data_mapped_size);
165 return true;
166}
167
168bool FlagParser::run_handler(const char *name, const char *value) {
169 for (int i = 0; i < n_flags_; ++i) {
170 if (internal_strcmp(name, flags_[i].name) == 0)
171 return flags_[i].handler->Parse(value);
172 }
173 // Unrecognized flag. This is not a fatal error, we may print a warning later.
174 unknown_flags.Add(name);
175 return true;
176}
177
178void FlagParser::RegisterHandler(const char *name, FlagHandlerBase *handler,
179 const char *desc) {
180 CHECK_LT(n_flags_, kMaxFlags);
181 flags_[n_flags_].name = name;
182 flags_[n_flags_].desc = desc;
183 flags_[n_flags_].handler = handler;
184 ++n_flags_;
185}
186
187FlagParser::FlagParser() : n_flags_(0), buf_(nullptr), pos_(0) {
188 flags_ = (Flag *)Alloc.Allocate(sizeof(Flag) * kMaxFlags);
189}
190
191} // namespace __sanitizer
lib/tsan/sanitizer_common/sanitizer_flag_parser.h created+204
...@@ -0,0 +1,204 @@
1//===-- sanitizer_flag_parser.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/AddressSanitizer runtime.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef SANITIZER_FLAG_REGISTRY_H
14#define SANITIZER_FLAG_REGISTRY_H
15
16#include "sanitizer_internal_defs.h"
17#include "sanitizer_libc.h"
18#include "sanitizer_common.h"
19
20namespace __sanitizer {
21
22class FlagHandlerBase {
23 public:
24 virtual bool Parse(const char *value) { return false; }
25 // Write the C string representation of the current value (truncated to fit)
26 // into the buffer of size `size`. Returns false if truncation occurred and
27 // returns true otherwise.
28 virtual bool Format(char *buffer, uptr size) {
29 if (size > 0)
30 buffer[0] = '\0';
31 return false;
32 }
33
34 protected:
35 ~FlagHandlerBase() {}
36
37 inline bool FormatString(char *buffer, uptr size, const char *str_to_use) {
38 uptr num_symbols_should_write =
39 internal_snprintf(buffer, size, "%s", str_to_use);
40 return num_symbols_should_write < size;
41 }
42};
43
44template <typename T>
45class FlagHandler : public FlagHandlerBase {
46 T *t_;
47
48 public:
49 explicit FlagHandler(T *t) : t_(t) {}
50 bool Parse(const char *value) final;
51 bool Format(char *buffer, uptr size) final;
52};
53
54inline bool ParseBool(const char *value, bool *b) {
55 if (internal_strcmp(value, "0") == 0 ||
56 internal_strcmp(value, "no") == 0 ||
57 internal_strcmp(value, "false") == 0) {
58 *b = false;
59 return true;
60 }
61 if (internal_strcmp(value, "1") == 0 ||
62 internal_strcmp(value, "yes") == 0 ||
63 internal_strcmp(value, "true") == 0) {
64 *b = true;
65 return true;
66 }
67 return false;
68}
69
70template <>
71inline bool FlagHandler<bool>::Parse(const char *value) {
72 if (ParseBool(value, t_)) return true;
73 Printf("ERROR: Invalid value for bool option: '%s'\n", value);
74 return false;
75}
76
77template <>
78inline bool FlagHandler<bool>::Format(char *buffer, uptr size) {
79 return FormatString(buffer, size, *t_ ? "true" : "false");
80}
81
82template <>
83inline bool FlagHandler<HandleSignalMode>::Parse(const char *value) {
84 bool b;
85 if (ParseBool(value, &b)) {
86 *t_ = b ? kHandleSignalYes : kHandleSignalNo;
87 return true;
88 }
89 if (internal_strcmp(value, "2") == 0 ||
90 internal_strcmp(value, "exclusive") == 0) {
91 *t_ = kHandleSignalExclusive;
92 return true;
93 }
94 Printf("ERROR: Invalid value for signal handler option: '%s'\n", value);
95 return false;
96}
97
98template <>
99inline bool FlagHandler<HandleSignalMode>::Format(char *buffer, uptr size) {
100 uptr num_symbols_should_write = internal_snprintf(buffer, size, "%d", *t_);
101 return num_symbols_should_write < size;
102}
103
104template <>
105inline bool FlagHandler<const char *>::Parse(const char *value) {
106 *t_ = value;
107 return true;
108}
109
110template <>
111inline bool FlagHandler<const char *>::Format(char *buffer, uptr size) {
112 return FormatString(buffer, size, *t_);
113}
114
115template <>
116inline bool FlagHandler<int>::Parse(const char *value) {
117 const char *value_end;
118 *t_ = internal_simple_strtoll(value, &value_end, 10);
119 bool ok = *value_end == 0;
120 if (!ok) Printf("ERROR: Invalid value for int option: '%s'\n", value);
121 return ok;
122}
123
124template <>
125inline bool FlagHandler<int>::Format(char *buffer, uptr size) {
126 uptr num_symbols_should_write = internal_snprintf(buffer, size, "%d", *t_);
127 return num_symbols_should_write < size;
128}
129
130template <>
131inline bool FlagHandler<uptr>::Parse(const char *value) {
132 const char *value_end;
133 *t_ = internal_simple_strtoll(value, &value_end, 10);
134 bool ok = *value_end == 0;
135 if (!ok) Printf("ERROR: Invalid value for uptr option: '%s'\n", value);
136 return ok;
137}
138
139template <>
140inline bool FlagHandler<uptr>::Format(char *buffer, uptr size) {
141 uptr num_symbols_should_write = internal_snprintf(buffer, size, "%p", *t_);
142 return num_symbols_should_write < size;
143}
144
145template <>
146inline bool FlagHandler<s64>::Parse(const char *value) {
147 const char *value_end;
148 *t_ = internal_simple_strtoll(value, &value_end, 10);
149 bool ok = *value_end == 0;
150 if (!ok) Printf("ERROR: Invalid value for s64 option: '%s'\n", value);
151 return ok;
152}
153
154template <>
155inline bool FlagHandler<s64>::Format(char *buffer, uptr size) {
156 uptr num_symbols_should_write = internal_snprintf(buffer, size, "%lld", *t_);
157 return num_symbols_should_write < size;
158}
159
160class FlagParser {
161 static const int kMaxFlags = 200;
162 struct Flag {
163 const char *name;
164 const char *desc;
165 FlagHandlerBase *handler;
166 } *flags_;
167 int n_flags_;
168
169 const char *buf_;
170 uptr pos_;
171
172 public:
173 FlagParser();
174 void RegisterHandler(const char *name, FlagHandlerBase *handler,
175 const char *desc);
176 void ParseString(const char *s, const char *env_name = 0);
177 void ParseStringFromEnv(const char *env_name);
178 bool ParseFile(const char *path, bool ignore_missing);
179 void PrintFlagDescriptions();
180
181 static LowLevelAllocator Alloc;
182
183 private:
184 void fatal_error(const char *err);
185 bool is_space(char c);
186 void skip_whitespace();
187 void parse_flags(const char *env_option_name);
188 void parse_flag(const char *env_option_name);
189 bool run_handler(const char *name, const char *value);
190 char *ll_strndup(const char *s, uptr n);
191};
192
193template <typename T>
194static void RegisterFlag(FlagParser *parser, const char *name, const char *desc,
195 T *var) {
196 FlagHandler<T> *fh = new (FlagParser::Alloc) FlagHandler<T>(var);
197 parser->RegisterHandler(name, fh, desc);
198}
199
200void ReportUnrecognizedFlags();
201
202} // namespace __sanitizer
203
204#endif // SANITIZER_FLAG_REGISTRY_H
lib/tsan/sanitizer_common/sanitizer_flags.cpp created+129
...@@ -0,0 +1,129 @@
1//===-- sanitizer_flags.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/AddressSanitizer runtime.
10//
11//===----------------------------------------------------------------------===//
12
13#include "sanitizer_flags.h"
14
15#include "sanitizer_common.h"
16#include "sanitizer_libc.h"
17#include "sanitizer_list.h"
18#include "sanitizer_flag_parser.h"
19
20namespace __sanitizer {
21
22CommonFlags common_flags_dont_use;
23
24void CommonFlags::SetDefaults() {
25#define COMMON_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
26#include "sanitizer_flags.inc"
27#undef COMMON_FLAG
28}
29
30void CommonFlags::CopyFrom(const CommonFlags &other) {
31 internal_memcpy(this, &other, sizeof(*this));
32}
33
34// Copy the string from "s" to "out", making the following substitutions:
35// %b = binary basename
36// %p = pid
37void SubstituteForFlagValue(const char *s, char *out, uptr out_size) {
38 char *out_end = out + out_size;
39 while (*s && out < out_end - 1) {
40 if (s[0] != '%') {
41 *out++ = *s++;
42 continue;
43 }
44 switch (s[1]) {
45 case 'b': {
46 const char *base = GetProcessName();
47 CHECK(base);
48 while (*base && out < out_end - 1)
49 *out++ = *base++;
50 s += 2; // skip "%b"
51 break;
52 }
53 case 'p': {
54 int pid = internal_getpid();
55 char buf[32];
56 char *buf_pos = buf + 32;
57 do {
58 *--buf_pos = (pid % 10) + '0';
59 pid /= 10;
60 } while (pid);
61 while (buf_pos < buf + 32 && out < out_end - 1)
62 *out++ = *buf_pos++;
63 s += 2; // skip "%p"
64 break;
65 }
66 default:
67 *out++ = *s++;
68 break;
69 }
70 }
71 CHECK(out < out_end - 1);
72 *out = '\0';
73}
74
75class FlagHandlerInclude : public FlagHandlerBase {
76 FlagParser *parser_;
77 bool ignore_missing_;
78 const char *original_path_;
79
80 public:
81 explicit FlagHandlerInclude(FlagParser *parser, bool ignore_missing)
82 : parser_(parser), ignore_missing_(ignore_missing), original_path_("") {}
83 bool Parse(const char *value) final {
84 original_path_ = value;
85 if (internal_strchr(value, '%')) {
86 char *buf = (char *)MmapOrDie(kMaxPathLength, "FlagHandlerInclude");
87 SubstituteForFlagValue(value, buf, kMaxPathLength);
88 bool res = parser_->ParseFile(buf, ignore_missing_);
89 UnmapOrDie(buf, kMaxPathLength);
90 return res;
91 }
92 return parser_->ParseFile(value, ignore_missing_);
93 }
94 bool Format(char *buffer, uptr size) {
95 // Note `original_path_` isn't actually what's parsed due to `%`
96 // substitutions. Printing the substituted path would require holding onto
97 // mmap'ed memory.
98 return FormatString(buffer, size, original_path_);
99 }
100};
101
102void RegisterIncludeFlags(FlagParser *parser, CommonFlags *cf) {
103 FlagHandlerInclude *fh_include = new (FlagParser::Alloc)
104 FlagHandlerInclude(parser, /*ignore_missing*/ false);
105 parser->RegisterHandler("include", fh_include,
106 "read more options from the given file");
107 FlagHandlerInclude *fh_include_if_exists = new (FlagParser::Alloc)
108 FlagHandlerInclude(parser, /*ignore_missing*/ true);
109 parser->RegisterHandler(
110 "include_if_exists", fh_include_if_exists,
111 "read more options from the given file (if it exists)");
112}
113
114void RegisterCommonFlags(FlagParser *parser, CommonFlags *cf) {
115#define COMMON_FLAG(Type, Name, DefaultValue, Description) \
116 RegisterFlag(parser, #Name, Description, &cf->Name);
117#include "sanitizer_flags.inc"
118#undef COMMON_FLAG
119
120 RegisterIncludeFlags(parser, cf);
121}
122
123void InitializeCommonFlags(CommonFlags *cf) {
124 // need to record coverage to generate coverage report.
125 cf->coverage |= cf->html_cov_report;
126 SetVerbosity(cf->verbosity);
127}
128
129} // namespace __sanitizer
lib/tsan/sanitizer_common/sanitizer_flags.h created+67
...@@ -0,0 +1,67 @@
1//===-- sanitizer_flags.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/AddressSanitizer runtime.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef SANITIZER_FLAGS_H
14#define SANITIZER_FLAGS_H
15
16#include "sanitizer_internal_defs.h"
17
18namespace __sanitizer {
19
20enum HandleSignalMode {
21 kHandleSignalNo,
22 kHandleSignalYes,
23 kHandleSignalExclusive,
24};
25
26struct CommonFlags {
27#define COMMON_FLAG(Type, Name, DefaultValue, Description) Type Name;
28#include "sanitizer_flags.inc"
29#undef COMMON_FLAG
30
31 void SetDefaults();
32 void CopyFrom(const CommonFlags &other);
33};
34
35// Functions to get/set global CommonFlags shared by all sanitizer runtimes:
36extern CommonFlags common_flags_dont_use;
37inline const CommonFlags *common_flags() {
38 return &common_flags_dont_use;
39}
40
41inline void SetCommonFlagsDefaults() {
42 common_flags_dont_use.SetDefaults();
43}
44
45// This function can only be used to setup tool-specific overrides for
46// CommonFlags defaults. Generally, it should only be used right after
47// SetCommonFlagsDefaults(), but before ParseCommonFlagsFromString(), and
48// only during the flags initialization (i.e. before they are used for
49// the first time).
50inline void OverrideCommonFlags(const CommonFlags &cf) {
51 common_flags_dont_use.CopyFrom(cf);
52}
53
54void SubstituteForFlagValue(const char *s, char *out, uptr out_size);
55
56class FlagParser;
57void RegisterCommonFlags(FlagParser *parser,
58 CommonFlags *cf = &common_flags_dont_use);
59void RegisterIncludeFlags(FlagParser *parser, CommonFlags *cf);
60
61// Should be called after parsing all flags. Sets up common flag values
62// and perform initializations common to all sanitizers (e.g. setting
63// verbosity).
64void InitializeCommonFlags(CommonFlags *cf = &common_flags_dont_use);
65} // namespace __sanitizer
66
67#endif // SANITIZER_FLAGS_H
lib/tsan/sanitizer_common/sanitizer_flags.inc created+250
...@@ -0,0 +1,250 @@
1//===-- sanitizer_flags.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 describes common flags available in all sanitizers.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef COMMON_FLAG
14#error "Define COMMON_FLAG prior to including this file!"
15#endif
16
17// COMMON_FLAG(Type, Name, DefaultValue, Description)
18// Supported types: bool, const char *, int, uptr.
19// Default value must be a compile-time constant.
20// Description must be a string literal.
21
22COMMON_FLAG(
23 bool, symbolize, true,
24 "If set, use the online symbolizer from common sanitizer runtime to turn "
25 "virtual addresses to file/line locations.")
26COMMON_FLAG(
27 const char *, external_symbolizer_path, nullptr,
28 "Path to external symbolizer. If empty, the tool will search $PATH for "
29 "the symbolizer.")
30COMMON_FLAG(
31 bool, allow_addr2line, false,
32 "If set, allows online symbolizer to run addr2line binary to symbolize "
33 "stack traces (addr2line will only be used if llvm-symbolizer binary is "
34 "unavailable.")
35COMMON_FLAG(const char *, strip_path_prefix, "",
36 "Strips this prefix from file paths in error reports.")
37COMMON_FLAG(bool, fast_unwind_on_check, false,
38 "If available, use the fast frame-pointer-based unwinder on "
39 "internal CHECK failures.")
40COMMON_FLAG(bool, fast_unwind_on_fatal, false,
41 "If available, use the fast frame-pointer-based unwinder on fatal "
42 "errors.")
43COMMON_FLAG(bool, fast_unwind_on_malloc, true,
44 "If available, use the fast frame-pointer-based unwinder on "
45 "malloc/free.")
46COMMON_FLAG(bool, handle_ioctl, false, "Intercept and handle ioctl requests.")
47COMMON_FLAG(int, malloc_context_size, 1,
48 "Max number of stack frames kept for each allocation/deallocation.")
49COMMON_FLAG(
50 const char *, log_path, "stderr",
51 "Write logs to \"log_path.pid\". The special values are \"stdout\" and "
52 "\"stderr\". The default is \"stderr\".")
53COMMON_FLAG(
54 bool, log_exe_name, false,
55 "Mention name of executable when reporting error and "
56 "append executable name to logs (as in \"log_path.exe_name.pid\").")
57COMMON_FLAG(
58 bool, log_to_syslog, (bool)SANITIZER_ANDROID || (bool)SANITIZER_MAC,
59 "Write all sanitizer output to syslog in addition to other means of "
60 "logging.")
61COMMON_FLAG(
62 int, verbosity, 0,
63 "Verbosity level (0 - silent, 1 - a bit of output, 2+ - more output).")
64COMMON_FLAG(bool, strip_env, 1,
65 "Whether to remove the sanitizer from DYLD_INSERT_LIBRARIES to "
66 "avoid passing it to children. Default is true.")
67COMMON_FLAG(bool, detect_leaks, !SANITIZER_MAC, "Enable memory leak detection.")
68COMMON_FLAG(
69 bool, leak_check_at_exit, true,
70 "Invoke leak checking in an atexit handler. Has no effect if "
71 "detect_leaks=false, or if __lsan_do_leak_check() is called before the "
72 "handler has a chance to run.")
73COMMON_FLAG(bool, allocator_may_return_null, false,
74 "If false, the allocator will crash instead of returning 0 on "
75 "out-of-memory.")
76COMMON_FLAG(bool, print_summary, true,
77 "If false, disable printing error summaries in addition to error "
78 "reports.")
79COMMON_FLAG(int, print_module_map, 0,
80 "OS X only (0 - don't print, 1 - print only once before process "
81 "exits, 2 - print after each report).")
82COMMON_FLAG(bool, check_printf, true, "Check printf arguments.")
83#define COMMON_FLAG_HANDLE_SIGNAL_HELP(signal) \
84 "Controls custom tool's " #signal " handler (0 - do not registers the " \
85 "handler, 1 - register the handler and allow user to set own, " \
86 "2 - registers the handler and block user from changing it). "
87COMMON_FLAG(HandleSignalMode, handle_segv, kHandleSignalYes,
88 COMMON_FLAG_HANDLE_SIGNAL_HELP(SIGSEGV))
89COMMON_FLAG(HandleSignalMode, handle_sigbus, kHandleSignalYes,
90 COMMON_FLAG_HANDLE_SIGNAL_HELP(SIGBUS))
91COMMON_FLAG(HandleSignalMode, handle_abort, kHandleSignalNo,
92 COMMON_FLAG_HANDLE_SIGNAL_HELP(SIGABRT))
93COMMON_FLAG(HandleSignalMode, handle_sigill, kHandleSignalNo,
94 COMMON_FLAG_HANDLE_SIGNAL_HELP(SIGILL))
95COMMON_FLAG(HandleSignalMode, handle_sigtrap, kHandleSignalNo,
96 COMMON_FLAG_HANDLE_SIGNAL_HELP(SIGTRAP))
97COMMON_FLAG(HandleSignalMode, handle_sigfpe, kHandleSignalYes,
98 COMMON_FLAG_HANDLE_SIGNAL_HELP(SIGFPE))
99#undef COMMON_FLAG_HANDLE_SIGNAL_HELP
100COMMON_FLAG(bool, allow_user_segv_handler, true,
101 "Deprecated. True has no effect, use handle_sigbus=1. If false, "
102 "handle_*=1 will be upgraded to handle_*=2.")
103COMMON_FLAG(bool, use_sigaltstack, true,
104 "If set, uses alternate stack for signal handling.")
105COMMON_FLAG(bool, detect_deadlocks, true,
106 "If set, deadlock detection is enabled.")
107COMMON_FLAG(
108 uptr, clear_shadow_mmap_threshold, 64 * 1024,
109 "Large shadow regions are zero-filled using mmap(NORESERVE) instead of "
110 "memset(). This is the threshold size in bytes.")
111COMMON_FLAG(const char *, color, "auto",
112 "Colorize reports: (always|never|auto).")
113COMMON_FLAG(
114 bool, legacy_pthread_cond, false,
115 "Enables support for dynamic libraries linked with libpthread 2.2.5.")
116COMMON_FLAG(bool, intercept_tls_get_addr, false, "Intercept __tls_get_addr.")
117COMMON_FLAG(bool, help, false, "Print the flag descriptions.")
118COMMON_FLAG(uptr, mmap_limit_mb, 0,
119 "Limit the amount of mmap-ed memory (excluding shadow) in Mb; "
120 "not a user-facing flag, used mosly for testing the tools")
121COMMON_FLAG(uptr, hard_rss_limit_mb, 0,
122 "Hard RSS limit in Mb."
123 " If non-zero, a background thread is spawned at startup"
124 " which periodically reads RSS and aborts the process if the"
125 " limit is reached")
126COMMON_FLAG(uptr, soft_rss_limit_mb, 0,
127 "Soft RSS limit in Mb."
128 " If non-zero, a background thread is spawned at startup"
129 " which periodically reads RSS. If the limit is reached"
130 " all subsequent malloc/new calls will fail or return NULL"
131 " (depending on the value of allocator_may_return_null)"
132 " until the RSS goes below the soft limit."
133 " This limit does not affect memory allocations other than"
134 " malloc/new.")
135COMMON_FLAG(uptr, max_allocation_size_mb, 0,
136 "If non-zero, malloc/new calls larger than this size will return "
137 "nullptr (or crash if allocator_may_return_null=false).")
138COMMON_FLAG(bool, heap_profile, false, "Experimental heap profiler, asan-only")
139COMMON_FLAG(s32, allocator_release_to_os_interval_ms,
140 ((bool)SANITIZER_FUCHSIA || (bool)SANITIZER_WINDOWS) ? -1 : 5000,
141 "Only affects a 64-bit allocator. If set, tries to release unused "
142 "memory to the OS, but not more often than this interval (in "
143 "milliseconds). Negative values mean do not attempt to release "
144 "memory to the OS.\n")
145COMMON_FLAG(bool, can_use_proc_maps_statm, true,
146 "If false, do not attempt to read /proc/maps/statm."
147 " Mostly useful for testing sanitizers.")
148COMMON_FLAG(
149 bool, coverage, false,
150 "If set, coverage information will be dumped at program shutdown (if the "
151 "coverage instrumentation was enabled at compile time).")
152COMMON_FLAG(const char *, coverage_dir, ".",
153 "Target directory for coverage dumps. Defaults to the current "
154 "directory.")
155COMMON_FLAG(bool, full_address_space, false,
156 "Sanitize complete address space; "
157 "by default kernel area on 32-bit platforms will not be sanitized")
158COMMON_FLAG(bool, print_suppressions, true,
159 "Print matched suppressions at exit.")
160COMMON_FLAG(
161 bool, disable_coredump, (SANITIZER_WORDSIZE == 64) && !SANITIZER_GO,
162 "Disable core dumping. By default, disable_coredump=1 on 64-bit to avoid"
163 " dumping a 16T+ core file. Ignored on OSes that don't dump core by"
164 " default and for sanitizers that don't reserve lots of virtual memory.")
165COMMON_FLAG(bool, use_madv_dontdump, true,
166 "If set, instructs kernel to not store the (huge) shadow "
167 "in core file.")
168COMMON_FLAG(bool, symbolize_inline_frames, true,
169 "Print inlined frames in stacktraces. Defaults to true.")
170COMMON_FLAG(bool, symbolize_vs_style, false,
171 "Print file locations in Visual Studio style (e.g: "
172 " file(10,42): ...")
173COMMON_FLAG(int, dedup_token_length, 0,
174 "If positive, after printing a stack trace also print a short "
175 "string token based on this number of frames that will simplify "
176 "deduplication of the reports. "
177 "Example: 'DEDUP_TOKEN: foo-bar-main'. Default is 0.")
178COMMON_FLAG(const char *, stack_trace_format, "DEFAULT",
179 "Format string used to render stack frames. "
180 "See sanitizer_stacktrace_printer.h for the format description. "
181 "Use DEFAULT to get default format.")
182COMMON_FLAG(bool, no_huge_pages_for_shadow, true,
183 "If true, the shadow is not allowed to use huge pages. ")
184COMMON_FLAG(bool, strict_string_checks, false,
185 "If set check that string arguments are properly null-terminated")
186COMMON_FLAG(bool, intercept_strstr, true,
187 "If set, uses custom wrappers for strstr and strcasestr functions "
188 "to find more errors.")
189COMMON_FLAG(bool, intercept_strspn, true,
190 "If set, uses custom wrappers for strspn and strcspn function "
191 "to find more errors.")
192COMMON_FLAG(bool, intercept_strtok, true,
193 "If set, uses a custom wrapper for the strtok function "
194 "to find more errors.")
195COMMON_FLAG(bool, intercept_strpbrk, true,
196 "If set, uses custom wrappers for strpbrk function "
197 "to find more errors.")
198COMMON_FLAG(bool, intercept_strlen, true,
199 "If set, uses custom wrappers for strlen and strnlen functions "
200 "to find more errors.")
201COMMON_FLAG(bool, intercept_strndup, true,
202 "If set, uses custom wrappers for strndup functions "
203 "to find more errors.")
204COMMON_FLAG(bool, intercept_strchr, true,
205 "If set, uses custom wrappers for strchr, strchrnul, and strrchr "
206 "functions to find more errors.")
207COMMON_FLAG(bool, intercept_memcmp, true,
208 "If set, uses custom wrappers for memcmp function "
209 "to find more errors.")
210COMMON_FLAG(bool, strict_memcmp, true,
211 "If true, assume that memcmp(p1, p2, n) always reads n bytes before "
212 "comparing p1 and p2.")
213COMMON_FLAG(bool, intercept_memmem, true,
214 "If set, uses a wrapper for memmem() to find more errors.")
215COMMON_FLAG(bool, intercept_intrin, true,
216 "If set, uses custom wrappers for memset/memcpy/memmove "
217 "intrinsics to find more errors.")
218COMMON_FLAG(bool, intercept_stat, true,
219 "If set, uses custom wrappers for *stat functions "
220 "to find more errors.")
221COMMON_FLAG(bool, intercept_send, true,
222 "If set, uses custom wrappers for send* functions "
223 "to find more errors.")
224COMMON_FLAG(bool, decorate_proc_maps, (bool)SANITIZER_ANDROID,
225 "If set, decorate sanitizer mappings in /proc/self/maps with "
226 "user-readable names")
227COMMON_FLAG(int, exitcode, 1, "Override the program exit status if the tool "
228 "found an error")
229COMMON_FLAG(
230 bool, abort_on_error, (bool)SANITIZER_ANDROID || (bool)SANITIZER_MAC,
231 "If set, the tool calls abort() instead of _exit() after printing the "
232 "error report.")
233COMMON_FLAG(bool, suppress_equal_pcs, true,
234 "Deduplicate multiple reports for single source location in "
235 "halt_on_error=false mode (asan only).")
236COMMON_FLAG(bool, print_cmdline, false, "Print command line on crash "
237 "(asan only).")
238COMMON_FLAG(bool, html_cov_report, false, "Generate html coverage report.")
239COMMON_FLAG(const char *, sancov_path, "sancov", "Sancov tool location.")
240COMMON_FLAG(bool, dump_instruction_bytes, false,
241 "If true, dump 16 bytes starting at the instruction that caused SEGV")
242COMMON_FLAG(bool, dump_registers, true,
243 "If true, dump values of CPU registers when SEGV happens. Only "
244 "available on OS X for now.")
245COMMON_FLAG(bool, detect_write_exec, false,
246 "If true, triggers warning when writable-executable pages requests "
247 "are being made")
248COMMON_FLAG(bool, test_only_emulate_no_memorymap, false,
249 "TEST ONLY fail to read memory mappings to emulate sanitized "
250 "\"init\"")
lib/tsan/sanitizer_common/sanitizer_freebsd.h created+137
...@@ -0,0 +1,137 @@
1//===-- sanitizer_freebsd.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 FreeBSD-specific
10// definitions.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef SANITIZER_FREEBSD_H
15#define SANITIZER_FREEBSD_H
16
17#include "sanitizer_internal_defs.h"
18
19// x86-64 FreeBSD 9.2 and older define 'ucontext_t' incorrectly in
20// 32-bit mode.
21#if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32)
22#include <osreldate.h>
23#if __FreeBSD_version <= 902001 // v9.2
24#include <link.h>
25#include <sys/param.h>
26#include <ucontext.h>
27
28namespace __sanitizer {
29
30typedef unsigned long long __xuint64_t;
31
32typedef __int32_t __xregister_t;
33
34typedef struct __xmcontext {
35 __xregister_t mc_onstack;
36 __xregister_t mc_gs;
37 __xregister_t mc_fs;
38 __xregister_t mc_es;
39 __xregister_t mc_ds;
40 __xregister_t mc_edi;
41 __xregister_t mc_esi;
42 __xregister_t mc_ebp;
43 __xregister_t mc_isp;
44 __xregister_t mc_ebx;
45 __xregister_t mc_edx;
46 __xregister_t mc_ecx;
47 __xregister_t mc_eax;
48 __xregister_t mc_trapno;
49 __xregister_t mc_err;
50 __xregister_t mc_eip;
51 __xregister_t mc_cs;
52 __xregister_t mc_eflags;
53 __xregister_t mc_esp;
54 __xregister_t mc_ss;
55
56 int mc_len;
57 int mc_fpformat;
58 int mc_ownedfp;
59 __xregister_t mc_flags;
60
61 int mc_fpstate[128] __aligned(16);
62 __xregister_t mc_fsbase;
63 __xregister_t mc_gsbase;
64 __xregister_t mc_xfpustate;
65 __xregister_t mc_xfpustate_len;
66
67 int mc_spare2[4];
68} xmcontext_t;
69
70typedef struct __xucontext {
71 sigset_t uc_sigmask;
72 xmcontext_t uc_mcontext;
73
74 struct __ucontext *uc_link;
75 stack_t uc_stack;
76 int uc_flags;
77 int __spare__[4];
78} xucontext_t;
79
80struct xkinfo_vmentry {
81 int kve_structsize;
82 int kve_type;
83 __xuint64_t kve_start;
84 __xuint64_t kve_end;
85 __xuint64_t kve_offset;
86 __xuint64_t kve_vn_fileid;
87 __uint32_t kve_vn_fsid;
88 int kve_flags;
89 int kve_resident;
90 int kve_private_resident;
91 int kve_protection;
92 int kve_ref_count;
93 int kve_shadow_count;
94 int kve_vn_type;
95 __xuint64_t kve_vn_size;
96 __uint32_t kve_vn_rdev;
97 __uint16_t kve_vn_mode;
98 __uint16_t kve_status;
99 int _kve_ispare[12];
100 char kve_path[PATH_MAX];
101};
102
103typedef struct {
104 __uint32_t p_type;
105 __uint32_t p_offset;
106 __uint32_t p_vaddr;
107 __uint32_t p_paddr;
108 __uint32_t p_filesz;
109 __uint32_t p_memsz;
110 __uint32_t p_flags;
111 __uint32_t p_align;
112} XElf32_Phdr;
113
114struct xdl_phdr_info {
115 Elf_Addr dlpi_addr;
116 const char *dlpi_name;
117 const XElf32_Phdr *dlpi_phdr;
118 Elf_Half dlpi_phnum;
119 unsigned long long int dlpi_adds;
120 unsigned long long int dlpi_subs;
121 size_t dlpi_tls_modid;
122 void *dlpi_tls_data;
123};
124
125typedef int (*__xdl_iterate_hdr_callback)(struct xdl_phdr_info *, size_t,
126 void *);
127typedef int xdl_iterate_phdr_t(__xdl_iterate_hdr_callback, void *);
128
129#define xdl_iterate_phdr(callback, param) \
130 (((xdl_iterate_phdr_t *)dl_iterate_phdr)((callback), (param)))
131
132} // namespace __sanitizer
133
134#endif // __FreeBSD_version <= 902001
135#endif // SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32)
136
137#endif // SANITIZER_FREEBSD_H
lib/tsan/sanitizer_common/sanitizer_fuchsia.cpp created+531
...@@ -0,0 +1,531 @@
1//===-- sanitizer_fuchsia.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 shared between AddressSanitizer and other sanitizer
10// run-time libraries and implements Fuchsia-specific functions from
11// sanitizer_common.h.
12//===----------------------------------------------------------------------===//
13
14#include "sanitizer_fuchsia.h"
15#if SANITIZER_FUCHSIA
16
17#include "sanitizer_common.h"
18#include "sanitizer_libc.h"
19#include "sanitizer_mutex.h"
20
21#include <limits.h>
22#include <pthread.h>
23#include <stdlib.h>
24#include <unistd.h>
25#include <zircon/errors.h>
26#include <zircon/process.h>
27#include <zircon/syscalls.h>
28
29namespace __sanitizer {
30
31void NORETURN internal__exit(int exitcode) { _zx_process_exit(exitcode); }
32
33uptr internal_sched_yield() {
34 zx_status_t status = _zx_nanosleep(0);
35 CHECK_EQ(status, ZX_OK);
36 return 0; // Why doesn't this return void?
37}
38
39static void internal_nanosleep(zx_time_t ns) {
40 zx_status_t status = _zx_nanosleep(_zx_deadline_after(ns));
41 CHECK_EQ(status, ZX_OK);
42}
43
44unsigned int internal_sleep(unsigned int seconds) {
45 internal_nanosleep(ZX_SEC(seconds));
46 return 0;
47}
48
49u64 NanoTime() {
50 zx_time_t time;
51 zx_status_t status = _zx_clock_get(ZX_CLOCK_UTC, &time);
52 CHECK_EQ(status, ZX_OK);
53 return time;
54}
55
56u64 MonotonicNanoTime() { return _zx_clock_get_monotonic(); }
57
58uptr internal_getpid() {
59 zx_info_handle_basic_t info;
60 zx_status_t status =
61 _zx_object_get_info(_zx_process_self(), ZX_INFO_HANDLE_BASIC, &info,
62 sizeof(info), NULL, NULL);
63 CHECK_EQ(status, ZX_OK);
64 uptr pid = static_cast<uptr>(info.koid);
65 CHECK_EQ(pid, info.koid);
66 return pid;
67}
68
69int internal_dlinfo(void *handle, int request, void *p) {
70 UNIMPLEMENTED();
71}
72
73uptr GetThreadSelf() { return reinterpret_cast<uptr>(thrd_current()); }
74
75tid_t GetTid() { return GetThreadSelf(); }
76
77void Abort() { abort(); }
78
79int Atexit(void (*function)(void)) { return atexit(function); }
80
81void SleepForSeconds(int seconds) { internal_sleep(seconds); }
82
83void SleepForMillis(int millis) { internal_nanosleep(ZX_MSEC(millis)); }
84
85void GetThreadStackTopAndBottom(bool, uptr *stack_top, uptr *stack_bottom) {
86 pthread_attr_t attr;
87 CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0);
88 void *base;
89 size_t size;
90 CHECK_EQ(pthread_attr_getstack(&attr, &base, &size), 0);
91 CHECK_EQ(pthread_attr_destroy(&attr), 0);
92
93 *stack_bottom = reinterpret_cast<uptr>(base);
94 *stack_top = *stack_bottom + size;
95}
96
97void InitializePlatformEarly() {}
98void MaybeReexec() {}
99void CheckASLR() {}
100void CheckMPROTECT() {}
101void PlatformPrepareForSandboxing(__sanitizer_sandbox_arguments *args) {}
102void DisableCoreDumperIfNecessary() {}
103void InstallDeadlySignalHandlers(SignalHandlerType handler) {}
104void SetAlternateSignalStack() {}
105void UnsetAlternateSignalStack() {}
106void InitTlsSize() {}
107
108void PrintModuleMap() {}
109
110bool SignalContext::IsStackOverflow() const { return false; }
111void SignalContext::DumpAllRegisters(void *context) { UNIMPLEMENTED(); }
112const char *SignalContext::Describe() const { UNIMPLEMENTED(); }
113
114enum MutexState : int { MtxUnlocked = 0, MtxLocked = 1, MtxSleeping = 2 };
115
116BlockingMutex::BlockingMutex() {
117 // NOTE! It's important that this use internal_memset, because plain
118 // memset might be intercepted (e.g., actually be __asan_memset).
119 // Defining this so the compiler initializes each field, e.g.:
120 // BlockingMutex::BlockingMutex() : BlockingMutex(LINKER_INITIALIZED) {}
121 // might result in the compiler generating a call to memset, which would
122 // have the same problem.
123 internal_memset(this, 0, sizeof(*this));
124}
125
126void BlockingMutex::Lock() {
127 CHECK_EQ(owner_, 0);
128 atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
129 if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked)
130 return;
131 while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked) {
132 zx_status_t status =
133 _zx_futex_wait(reinterpret_cast<zx_futex_t *>(m), MtxSleeping,
134 ZX_HANDLE_INVALID, ZX_TIME_INFINITE);
135 if (status != ZX_ERR_BAD_STATE) // Normal race.
136 CHECK_EQ(status, ZX_OK);
137 }
138}
139
140void BlockingMutex::Unlock() {
141 atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
142 u32 v = atomic_exchange(m, MtxUnlocked, memory_order_release);
143 CHECK_NE(v, MtxUnlocked);
144 if (v == MtxSleeping) {
145 zx_status_t status = _zx_futex_wake(reinterpret_cast<zx_futex_t *>(m), 1);
146 CHECK_EQ(status, ZX_OK);
147 }
148}
149
150void BlockingMutex::CheckLocked() {
151 atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
152 CHECK_NE(MtxUnlocked, atomic_load(m, memory_order_relaxed));
153}
154
155uptr GetPageSize() { return PAGE_SIZE; }
156
157uptr GetMmapGranularity() { return PAGE_SIZE; }
158
159sanitizer_shadow_bounds_t ShadowBounds;
160
161uptr GetMaxUserVirtualAddress() {
162 ShadowBounds = __sanitizer_shadow_bounds();
163 return ShadowBounds.memory_limit - 1;
164}
165
166uptr GetMaxVirtualAddress() { return GetMaxUserVirtualAddress(); }
167
168static void *DoAnonymousMmapOrDie(uptr size, const char *mem_type,
169 bool raw_report, bool die_for_nomem) {
170 size = RoundUpTo(size, PAGE_SIZE);
171
172 zx_handle_t vmo;
173 zx_status_t status = _zx_vmo_create(size, 0, &vmo);
174 if (status != ZX_OK) {
175 if (status != ZX_ERR_NO_MEMORY || die_for_nomem)
176 ReportMmapFailureAndDie(size, mem_type, "zx_vmo_create", status,
177 raw_report);
178 return nullptr;
179 }
180 _zx_object_set_property(vmo, ZX_PROP_NAME, mem_type,
181 internal_strlen(mem_type));
182
183 // TODO(mcgrathr): Maybe allocate a VMAR for all sanitizer heap and use that?
184 uintptr_t addr;
185 status =
186 _zx_vmar_map(_zx_vmar_root_self(), ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, 0,
187 vmo, 0, size, &addr);
188 _zx_handle_close(vmo);
189
190 if (status != ZX_OK) {
191 if (status != ZX_ERR_NO_MEMORY || die_for_nomem)
192 ReportMmapFailureAndDie(size, mem_type, "zx_vmar_map", status,
193 raw_report);
194 return nullptr;
195 }
196
197 IncreaseTotalMmap(size);
198
199 return reinterpret_cast<void *>(addr);
200}
201
202void *MmapOrDie(uptr size, const char *mem_type, bool raw_report) {
203 return DoAnonymousMmapOrDie(size, mem_type, raw_report, true);
204}
205
206void *MmapNoReserveOrDie(uptr size, const char *mem_type) {
207 return MmapOrDie(size, mem_type);
208}
209
210void *MmapOrDieOnFatalError(uptr size, const char *mem_type) {
211 return DoAnonymousMmapOrDie(size, mem_type, false, false);
212}
213
214uptr ReservedAddressRange::Init(uptr init_size, const char *name,
215 uptr fixed_addr) {
216 init_size = RoundUpTo(init_size, PAGE_SIZE);
217 DCHECK_EQ(os_handle_, ZX_HANDLE_INVALID);
218 uintptr_t base;
219 zx_handle_t vmar;
220 zx_status_t status =
221 _zx_vmar_allocate(
222 _zx_vmar_root_self(),
223 ZX_VM_CAN_MAP_READ | ZX_VM_CAN_MAP_WRITE | ZX_VM_CAN_MAP_SPECIFIC,
224 0, init_size, &vmar, &base);
225 if (status != ZX_OK)
226 ReportMmapFailureAndDie(init_size, name, "zx_vmar_allocate", status);
227 base_ = reinterpret_cast<void *>(base);
228 size_ = init_size;
229 name_ = name;
230 os_handle_ = vmar;
231
232 return reinterpret_cast<uptr>(base_);
233}
234
235static uptr DoMmapFixedOrDie(zx_handle_t vmar, uptr fixed_addr, uptr map_size,
236 void *base, const char *name, bool die_for_nomem) {
237 uptr offset = fixed_addr - reinterpret_cast<uptr>(base);
238 map_size = RoundUpTo(map_size, PAGE_SIZE);
239 zx_handle_t vmo;
240 zx_status_t status = _zx_vmo_create(map_size, 0, &vmo);
241 if (status != ZX_OK) {
242 if (status != ZX_ERR_NO_MEMORY || die_for_nomem)
243 ReportMmapFailureAndDie(map_size, name, "zx_vmo_create", status);
244 return 0;
245 }
246 _zx_object_set_property(vmo, ZX_PROP_NAME, name, internal_strlen(name));
247 DCHECK_GE(base + size_, map_size + offset);
248 uintptr_t addr;
249
250 status =
251 _zx_vmar_map(vmar, ZX_VM_PERM_READ | ZX_VM_PERM_WRITE | ZX_VM_SPECIFIC,
252 offset, vmo, 0, map_size, &addr);
253 _zx_handle_close(vmo);
254 if (status != ZX_OK) {
255 if (status != ZX_ERR_NO_MEMORY || die_for_nomem) {
256 ReportMmapFailureAndDie(map_size, name, "zx_vmar_map", status);
257 }
258 return 0;
259 }
260 IncreaseTotalMmap(map_size);
261 return addr;
262}
263
264uptr ReservedAddressRange::Map(uptr fixed_addr, uptr map_size,
265 const char *name) {
266 return DoMmapFixedOrDie(os_handle_, fixed_addr, map_size, base_,
267 name_, false);
268}
269
270uptr ReservedAddressRange::MapOrDie(uptr fixed_addr, uptr map_size,
271 const char *name) {
272 return DoMmapFixedOrDie(os_handle_, fixed_addr, map_size, base_,
273 name_, true);
274}
275
276void UnmapOrDieVmar(void *addr, uptr size, zx_handle_t target_vmar) {
277 if (!addr || !size) return;
278 size = RoundUpTo(size, PAGE_SIZE);
279
280 zx_status_t status =
281 _zx_vmar_unmap(target_vmar, reinterpret_cast<uintptr_t>(addr), size);
282 if (status != ZX_OK) {
283 Report("ERROR: %s failed to deallocate 0x%zx (%zd) bytes at address %p\n",
284 SanitizerToolName, size, size, addr);
285 CHECK("unable to unmap" && 0);
286 }
287
288 DecreaseTotalMmap(size);
289}
290
291void ReservedAddressRange::Unmap(uptr addr, uptr size) {
292 CHECK_LE(size, size_);
293 const zx_handle_t vmar = static_cast<zx_handle_t>(os_handle_);
294 if (addr == reinterpret_cast<uptr>(base_)) {
295 if (size == size_) {
296 // Destroying the vmar effectively unmaps the whole mapping.
297 _zx_vmar_destroy(vmar);
298 _zx_handle_close(vmar);
299 os_handle_ = static_cast<uptr>(ZX_HANDLE_INVALID);
300 DecreaseTotalMmap(size);
301 return;
302 }
303 } else {
304 CHECK_EQ(addr + size, reinterpret_cast<uptr>(base_) + size_);
305 }
306 // Partial unmapping does not affect the fact that the initial range is still
307 // reserved, and the resulting unmapped memory can't be reused.
308 UnmapOrDieVmar(reinterpret_cast<void *>(addr), size, vmar);
309}
310
311// This should never be called.
312void *MmapFixedNoAccess(uptr fixed_addr, uptr size, const char *name) {
313 UNIMPLEMENTED();
314}
315
316void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment,
317 const char *mem_type) {
318 CHECK_GE(size, PAGE_SIZE);
319 CHECK(IsPowerOfTwo(size));
320 CHECK(IsPowerOfTwo(alignment));
321
322 zx_handle_t vmo;
323 zx_status_t status = _zx_vmo_create(size, 0, &vmo);
324 if (status != ZX_OK) {
325 if (status != ZX_ERR_NO_MEMORY)
326 ReportMmapFailureAndDie(size, mem_type, "zx_vmo_create", status, false);
327 return nullptr;
328 }
329 _zx_object_set_property(vmo, ZX_PROP_NAME, mem_type,
330 internal_strlen(mem_type));
331
332 // TODO(mcgrathr): Maybe allocate a VMAR for all sanitizer heap and use that?
333
334 // Map a larger size to get a chunk of address space big enough that
335 // it surely contains an aligned region of the requested size. Then
336 // overwrite the aligned middle portion with a mapping from the
337 // beginning of the VMO, and unmap the excess before and after.
338 size_t map_size = size + alignment;
339 uintptr_t addr;
340 status =
341 _zx_vmar_map(_zx_vmar_root_self(), ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, 0,
342 vmo, 0, map_size, &addr);
343 if (status == ZX_OK) {
344 uintptr_t map_addr = addr;
345 uintptr_t map_end = map_addr + map_size;
346 addr = RoundUpTo(map_addr, alignment);
347 uintptr_t end = addr + size;
348 if (addr != map_addr) {
349 zx_info_vmar_t info;
350 status = _zx_object_get_info(_zx_vmar_root_self(), ZX_INFO_VMAR, &info,
351 sizeof(info), NULL, NULL);
352 if (status == ZX_OK) {
353 uintptr_t new_addr;
354 status = _zx_vmar_map(
355 _zx_vmar_root_self(),
356 ZX_VM_PERM_READ | ZX_VM_PERM_WRITE | ZX_VM_SPECIFIC_OVERWRITE,
357 addr - info.base, vmo, 0, size, &new_addr);
358 if (status == ZX_OK) CHECK_EQ(new_addr, addr);
359 }
360 }
361 if (status == ZX_OK && addr != map_addr)
362 status = _zx_vmar_unmap(_zx_vmar_root_self(), map_addr, addr - map_addr);
363 if (status == ZX_OK && end != map_end)
364 status = _zx_vmar_unmap(_zx_vmar_root_self(), end, map_end - end);
365 }
366 _zx_handle_close(vmo);
367
368 if (status != ZX_OK) {
369 if (status != ZX_ERR_NO_MEMORY)
370 ReportMmapFailureAndDie(size, mem_type, "zx_vmar_map", status, false);
371 return nullptr;
372 }
373
374 IncreaseTotalMmap(size);
375
376 return reinterpret_cast<void *>(addr);
377}
378
379void UnmapOrDie(void *addr, uptr size) {
380 UnmapOrDieVmar(addr, size, _zx_vmar_root_self());
381}
382
383// This is used on the shadow mapping, which cannot be changed.
384// Zircon doesn't have anything like MADV_DONTNEED.
385void ReleaseMemoryPagesToOS(uptr beg, uptr end) {}
386
387void DumpProcessMap() {
388 // TODO(mcgrathr): write it
389 return;
390}
391
392bool IsAccessibleMemoryRange(uptr beg, uptr size) {
393 // TODO(mcgrathr): Figure out a better way.
394 zx_handle_t vmo;
395 zx_status_t status = _zx_vmo_create(size, 0, &vmo);
396 if (status == ZX_OK) {
397 status = _zx_vmo_write(vmo, reinterpret_cast<const void *>(beg), 0, size);
398 _zx_handle_close(vmo);
399 }
400 return status == ZX_OK;
401}
402
403// FIXME implement on this platform.
404void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size) {}
405
406bool ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size,
407 uptr *read_len, uptr max_len, error_t *errno_p) {
408 zx_handle_t vmo;
409 zx_status_t status = __sanitizer_get_configuration(file_name, &vmo);
410 if (status == ZX_OK) {
411 uint64_t vmo_size;
412 status = _zx_vmo_get_size(vmo, &vmo_size);
413 if (status == ZX_OK) {
414 if (vmo_size < max_len) max_len = vmo_size;
415 size_t map_size = RoundUpTo(max_len, PAGE_SIZE);
416 uintptr_t addr;
417 status = _zx_vmar_map(_zx_vmar_root_self(), ZX_VM_PERM_READ, 0, vmo, 0,
418 map_size, &addr);
419 if (status == ZX_OK) {
420 *buff = reinterpret_cast<char *>(addr);
421 *buff_size = map_size;
422 *read_len = max_len;
423 }
424 }
425 _zx_handle_close(vmo);
426 }
427 if (status != ZX_OK && errno_p) *errno_p = status;
428 return status == ZX_OK;
429}
430
431void RawWrite(const char *buffer) {
432 constexpr size_t size = 128;
433 static _Thread_local char line[size];
434 static _Thread_local size_t lastLineEnd = 0;
435 static _Thread_local size_t cur = 0;
436
437 while (*buffer) {
438 if (cur >= size) {
439 if (lastLineEnd == 0)
440 lastLineEnd = size;
441 __sanitizer_log_write(line, lastLineEnd);
442 internal_memmove(line, line + lastLineEnd, cur - lastLineEnd);
443 cur = cur - lastLineEnd;
444 lastLineEnd = 0;
445 }
446 if (*buffer == '\n')
447 lastLineEnd = cur + 1;
448 line[cur++] = *buffer++;
449 }
450 // Flush all complete lines before returning.
451 if (lastLineEnd != 0) {
452 __sanitizer_log_write(line, lastLineEnd);
453 internal_memmove(line, line + lastLineEnd, cur - lastLineEnd);
454 cur = cur - lastLineEnd;
455 lastLineEnd = 0;
456 }
457}
458
459void CatastrophicErrorWrite(const char *buffer, uptr length) {
460 __sanitizer_log_write(buffer, length);
461}
462
463char **StoredArgv;
464char **StoredEnviron;
465
466char **GetArgv() { return StoredArgv; }
467char **GetEnviron() { return StoredEnviron; }
468
469const char *GetEnv(const char *name) {
470 if (StoredEnviron) {
471 uptr NameLen = internal_strlen(name);
472 for (char **Env = StoredEnviron; *Env != 0; Env++) {
473 if (internal_strncmp(*Env, name, NameLen) == 0 && (*Env)[NameLen] == '=')
474 return (*Env) + NameLen + 1;
475 }
476 }
477 return nullptr;
478}
479
480uptr ReadBinaryName(/*out*/ char *buf, uptr buf_len) {
481 const char *argv0 = "<UNKNOWN>";
482 if (StoredArgv && StoredArgv[0]) {
483 argv0 = StoredArgv[0];
484 }
485 internal_strncpy(buf, argv0, buf_len);
486 return internal_strlen(buf);
487}
488
489uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len) {
490 return ReadBinaryName(buf, buf_len);
491}
492
493uptr MainThreadStackBase, MainThreadStackSize;
494
495bool GetRandom(void *buffer, uptr length, bool blocking) {
496 CHECK_LE(length, ZX_CPRNG_DRAW_MAX_LEN);
497 _zx_cprng_draw(buffer, length);
498 return true;
499}
500
501u32 GetNumberOfCPUs() {
502 return zx_system_get_num_cpus();
503}
504
505uptr GetRSS() { UNIMPLEMENTED(); }
506
507} // namespace __sanitizer
508
509using namespace __sanitizer;
510
511extern "C" {
512void __sanitizer_startup_hook(int argc, char **argv, char **envp,
513 void *stack_base, size_t stack_size) {
514 __sanitizer::StoredArgv = argv;
515 __sanitizer::StoredEnviron = envp;
516 __sanitizer::MainThreadStackBase = reinterpret_cast<uintptr_t>(stack_base);
517 __sanitizer::MainThreadStackSize = stack_size;
518}
519
520void __sanitizer_set_report_path(const char *path) {
521 // Handle the initialization code in each sanitizer, but no other calls.
522 // This setting is never consulted on Fuchsia.
523 DCHECK_EQ(path, common_flags()->log_path);
524}
525
526void __sanitizer_set_report_fd(void *fd) {
527 UNREACHABLE("not available on Fuchsia");
528}
529} // extern "C"
530
531#endif // SANITIZER_FUCHSIA
lib/tsan/sanitizer_common/sanitizer_fuchsia.h created+36
...@@ -0,0 +1,36 @@
1//===-- sanitizer_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// Fuchsia-specific sanitizer support.
10//
11//===---------------------------------------------------------------------===//
12#ifndef SANITIZER_FUCHSIA_H
13#define SANITIZER_FUCHSIA_H
14
15#include "sanitizer_platform.h"
16#if SANITIZER_FUCHSIA
17
18#include "sanitizer_common.h"
19
20#include <zircon/sanitizer.h>
21#include <zircon/syscalls/object.h>
22
23namespace __sanitizer {
24
25extern uptr MainThreadStackBase, MainThreadStackSize;
26extern sanitizer_shadow_bounds_t ShadowBounds;
27
28struct MemoryMappingLayoutData {
29 InternalMmapVector<zx_info_maps_t> data;
30 size_t current; // Current index into the vector.
31};
32
33} // namespace __sanitizer
34
35#endif // SANITIZER_FUCHSIA
36#endif // SANITIZER_FUCHSIA_H
lib/tsan/sanitizer_common/sanitizer_getauxval.h created+59
...@@ -0,0 +1,59 @@
1//===-- sanitizer_getauxval.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// Common getauxval() guards and definitions.
10// getauxval() is not defined until glibc version 2.16, or until API level 21
11// for Android.
12// Implement the getauxval() compat function for NetBSD.
13//
14//===----------------------------------------------------------------------===//
15
16#ifndef SANITIZER_GETAUXVAL_H
17#define SANITIZER_GETAUXVAL_H
18
19#include "sanitizer_platform.h"
20#include "sanitizer_glibc_version.h"
21
22#if SANITIZER_LINUX || SANITIZER_FUCHSIA
23
24# if __GLIBC_PREREQ(2, 16) || (SANITIZER_ANDROID && __ANDROID_API__ >= 21) || \
25 SANITIZER_FUCHSIA
26# define SANITIZER_USE_GETAUXVAL 1
27# else
28# define SANITIZER_USE_GETAUXVAL 0
29# endif
30
31# if SANITIZER_USE_GETAUXVAL
32# include <sys/auxv.h>
33# else
34// The weak getauxval definition allows to check for the function at runtime.
35// This is useful for Android, when compiled at a lower API level yet running
36// on a more recent platform that offers the function.
37extern "C" SANITIZER_WEAK_ATTRIBUTE unsigned long getauxval(unsigned long type);
38# endif
39
40#elif SANITIZER_NETBSD
41
42#define SANITIZER_USE_GETAUXVAL 1
43
44#include <dlfcn.h>
45#include <elf.h>
46
47static inline decltype(AuxInfo::a_v) getauxval(decltype(AuxInfo::a_type) type) {
48 for (const AuxInfo *aux = (const AuxInfo *)_dlauxinfo();
49 aux->a_type != AT_NULL; ++aux) {
50 if (type == aux->a_type)
51 return aux->a_v;
52 }
53
54 return 0;
55}
56
57#endif
58
59#endif // SANITIZER_GETAUXVAL_H
lib/tsan/sanitizer_common/sanitizer_glibc_version.h created+26
...@@ -0,0 +1,26 @@
1//===-- sanitizer_glibc_version.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//===----------------------------------------------------------------------===//
12
13#ifndef SANITIZER_GLIBC_VERSION_H
14#define SANITIZER_GLIBC_VERSION_H
15
16#include "sanitizer_platform.h"
17
18#if SANITIZER_LINUX || SANITIZER_FUCHSIA
19#include <features.h>
20#endif
21
22#ifndef __GLIBC_PREREQ
23#define __GLIBC_PREREQ(x, y) 0
24#endif
25
26#endif
lib/tsan/sanitizer_common/sanitizer_hash.h created+43
...@@ -0,0 +1,43 @@
1//===-- sanitizer_common.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 implements a simple hash function.
10//===----------------------------------------------------------------------===//
11
12#ifndef SANITIZER_HASH_H
13#define SANITIZER_HASH_H
14
15#include "sanitizer_internal_defs.h"
16
17namespace __sanitizer {
18class MurMur2HashBuilder {
19 static const u32 m = 0x5bd1e995;
20 static const u32 seed = 0x9747b28c;
21 static const u32 r = 24;
22 u32 h;
23
24 public:
25 explicit MurMur2HashBuilder(u32 init = 0) { h = seed ^ init; }
26 void add(u32 k) {
27 k *= m;
28 k ^= k >> r;
29 k *= m;
30 h *= m;
31 h ^= k;
32 }
33 u32 get() {
34 u32 x = h;
35 x ^= x >> 13;
36 x *= m;
37 x ^= x >> 15;
38 return x;
39 }
40};
41} //namespace __sanitizer
42
43#endif // SANITIZER_HASH_H
lib/tsan/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc created+1535
...@@ -0,0 +1,1535 @@
1//===-- sanitizer_interceptors_ioctl_netbsd.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// Ioctl handling in common sanitizer interceptors.
10//===----------------------------------------------------------------------===//
11
12#if SANITIZER_NETBSD
13
14#include "sanitizer_flags.h"
15
16struct ioctl_desc {
17 unsigned req;
18 // FIXME: support read+write arguments. Currently READWRITE and WRITE do the
19 // same thing.
20 // XXX: The declarations below may use WRITE instead of READWRITE, unless
21 // explicitly noted.
22 enum { NONE, READ, WRITE, READWRITE, CUSTOM } type : 3;
23 unsigned size : 29;
24 const char *name;
25};
26
27const unsigned ioctl_table_max = 1238;
28static ioctl_desc ioctl_table[ioctl_table_max];
29static unsigned ioctl_table_size = 0;
30
31// This can not be declared as a global, because references to struct_*_sz
32// require a global initializer. And this table must be available before global
33// initializers are run.
34static void ioctl_table_fill() {
35#define _(rq, tp, sz) \
36 if (IOCTL_##rq != IOCTL_NOT_PRESENT) { \
37 CHECK(ioctl_table_size < ioctl_table_max); \
38 ioctl_table[ioctl_table_size].req = IOCTL_##rq; \
39 ioctl_table[ioctl_table_size].type = ioctl_desc::tp; \
40 ioctl_table[ioctl_table_size].size = sz; \
41 ioctl_table[ioctl_table_size].name = #rq; \
42 ++ioctl_table_size; \
43 }
44
45 /* Entries from file: altq/altq_afmap.h */
46 _(AFM_ADDFMAP, READWRITE, struct_atm_flowmap_sz);
47 _(AFM_DELFMAP, READWRITE, struct_atm_flowmap_sz);
48 _(AFM_CLEANFMAP, READWRITE, struct_atm_flowmap_sz);
49 _(AFM_GETFMAP, READWRITE, struct_atm_flowmap_sz);
50 /* Entries from file: altq/altq.h */
51 _(ALTQGTYPE, READWRITE, struct_altqreq_sz);
52 _(ALTQTBRSET, READ, struct_tbrreq_sz);
53 _(ALTQTBRGET, READWRITE, struct_tbrreq_sz);
54 /* Entries from file: altq/altq_blue.h */
55 _(BLUE_IF_ATTACH, READ, struct_blue_interface_sz);
56 _(BLUE_DISABLE, READ, struct_blue_interface_sz);
57 _(BLUE_CONFIG, READWRITE, struct_blue_conf_sz);
58 _(BLUE_GETSTATS, READWRITE, struct_blue_stats_sz);
59 /* Entries from file: altq/altq_cbq.h */
60 _(CBQ_ENABLE, READ, struct_cbq_interface_sz);
61 _(CBQ_ADD_CLASS, READWRITE, struct_cbq_add_class_sz);
62 _(CBQ_DEL_CLASS, READ, struct_cbq_delete_class_sz);
63 _(CBQ_MODIFY_CLASS, READWRITE, struct_cbq_modify_class_sz);
64 _(CBQ_DEL_FILTER, READ, struct_cbq_delete_filter_sz);
65 _(CBQ_GETSTATS, READWRITE, struct_cbq_getstats_sz);
66 /* Entries from file: altq/altq_cdnr.h */
67 _(CDNR_IF_DETACH, READ, struct_cdnr_interface_sz);
68 _(CDNR_ADD_FILTER, READWRITE, struct_cdnr_add_filter_sz);
69 _(CDNR_GETSTATS, READWRITE, struct_cdnr_get_stats_sz);
70 _(CDNR_ADD_ELEM, READWRITE, struct_cdnr_add_element_sz);
71 _(CDNR_DEL_ELEM, READ, struct_cdnr_delete_element_sz);
72 _(CDNR_ADD_TBM, READWRITE, struct_cdnr_add_tbmeter_sz);
73 _(CDNR_MOD_TBM, READ, struct_cdnr_modify_tbmeter_sz);
74 _(CDNR_TBM_STATS, READWRITE, struct_cdnr_tbmeter_stats_sz);
75 _(CDNR_ADD_TCM, READWRITE, struct_cdnr_add_trtcm_sz);
76 _(CDNR_MOD_TCM, READWRITE, struct_cdnr_modify_trtcm_sz);
77 _(CDNR_TCM_STATS, READWRITE, struct_cdnr_tcm_stats_sz);
78 _(CDNR_ADD_TSW, READWRITE, struct_cdnr_add_tswtcm_sz);
79 _(CDNR_MOD_TSW, READWRITE, struct_cdnr_modify_tswtcm_sz);
80 /* Entries from file: altq/altq_fifoq.h */
81 _(FIFOQ_CONFIG, READWRITE, struct_fifoq_conf_sz);
82 _(FIFOQ_GETSTATS, READWRITE, struct_fifoq_getstats_sz);
83 /* Entries from file: altq/altq_hfsc.h */
84 _(HFSC_CLEAR_HIERARCHY, READ, struct_hfsc_interface_sz);
85 _(HFSC_ADD_CLASS, READWRITE, struct_hfsc_add_class_sz);
86 _(HFSC_GETSTATS, READWRITE, struct_hfsc_class_stats_sz);
87 /* Entries from file: altq/altq_jobs.h */
88 _(JOBS_IF_ATTACH, READ, struct_jobs_attach_sz);
89 _(JOBS_IF_DETACH, READ, struct_jobs_interface_sz);
90 _(JOBS_ENABLE, READ, struct_jobs_interface_sz);
91 _(JOBS_DISABLE, READ, struct_jobs_interface_sz);
92 _(JOBS_CLEAR, READ, struct_jobs_interface_sz);
93 _(JOBS_ADD_CLASS, READWRITE, struct_jobs_add_class_sz);
94 _(JOBS_MOD_CLASS, READ, struct_jobs_modify_class_sz);
95 /* Entries from file: altq/altq_priq.h */
96 _(PRIQ_IF_ATTACH, READ, struct_priq_interface_sz);
97 _(PRIQ_CLEAR, READ, struct_priq_interface_sz);
98 _(PRIQ_ADD_CLASS, READWRITE, struct_priq_add_class_sz);
99 _(PRIQ_DEL_CLASS, READ, struct_priq_delete_class_sz);
100 _(PRIQ_MOD_CLASS, READ, struct_priq_modify_class_sz);
101 _(PRIQ_ADD_FILTER, READWRITE, struct_priq_add_filter_sz);
102 _(PRIQ_DEL_FILTER, READ, struct_priq_delete_filter_sz);
103 _(PRIQ_GETSTATS, READWRITE, struct_priq_class_stats_sz);
104 /* Entries from file: altq/altq_red.h */
105 _(RED_CONFIG, READWRITE, struct_red_conf_sz);
106 _(RED_GETSTATS, READWRITE, struct_red_stats_sz);
107 _(RED_SETDEFAULTS, READ, struct_redparams_sz);
108 /* Entries from file: altq/altq_rio.h */
109 _(RIO_CONFIG, READWRITE, struct_rio_conf_sz);
110 _(RIO_GETSTATS, READWRITE, struct_rio_stats_sz);
111 _(RIO_SETDEFAULTS, READ, struct_redparams_sz);
112 /* Entries from file: altq/altq_wfq.h */
113 _(WFQ_CONFIG, READWRITE, struct_wfq_conf_sz);
114 _(WFQ_GET_QID, READWRITE, struct_wfq_getqid_sz);
115 _(WFQ_SET_WEIGHT, READWRITE, struct_wfq_setweight_sz);
116 /* Entries from file: crypto/cryptodev.h */
117 _(CRIOGET, READWRITE, sizeof(u32));
118 _(CIOCFSESSION, READ, sizeof(u32));
119 _(CIOCKEY, READWRITE, struct_crypt_kop_sz);
120 _(CIOCNFKEYM, READWRITE, struct_crypt_mkop_sz);
121 _(CIOCNFSESSION, READ, struct_crypt_sfop_sz);
122 _(CIOCNCRYPTRETM, READWRITE, struct_cryptret_sz);
123 _(CIOCNCRYPTRET, READWRITE, struct_crypt_result_sz);
124 _(CIOCGSESSION, READWRITE, struct_session_op_sz);
125 _(CIOCNGSESSION, READWRITE, struct_crypt_sgop_sz);
126 _(CIOCCRYPT, READWRITE, struct_crypt_op_sz);
127 _(CIOCNCRYPTM, READWRITE, struct_crypt_mop_sz);
128 _(CIOCASYMFEAT, WRITE, sizeof(u32));
129 /* Entries from file: dev/apm/apmio.h */
130 _(APM_IOC_REJECT, READ, struct_apm_event_info_sz);
131 _(OAPM_IOC_GETPOWER, WRITE, struct_apm_power_info_sz);
132 _(APM_IOC_GETPOWER, READWRITE, struct_apm_power_info_sz);
133 _(APM_IOC_NEXTEVENT, WRITE, struct_apm_event_info_sz);
134 _(APM_IOC_DEV_CTL, READ, struct_apm_ctl_sz);
135 /* Entries from file: dev/dm/netbsd-dm.h */
136 _(NETBSD_DM_IOCTL, READWRITE, struct_plistref_sz);
137 /* Entries from file: dev/dmover/dmover_io.h */
138 _(DMIO_SETFUNC, READ, struct_dmio_setfunc_sz);
139 /* Entries from file: dev/dtv/dtvio_demux.h */
140 _(DMX_START, NONE, 0);
141 _(DMX_STOP, NONE, 0);
142 _(DMX_SET_FILTER, READ, struct_dmx_sct_filter_params_sz);
143 _(DMX_SET_PES_FILTER, READ, struct_dmx_pes_filter_params_sz);
144 _(DMX_SET_BUFFER_SIZE, NONE, 0);
145 _(DMX_GET_STC, READWRITE, struct_dmx_stc_sz);
146 _(DMX_ADD_PID, READ, sizeof(u16));
147 _(DMX_REMOVE_PID, READ, sizeof(u16));
148 _(DMX_GET_CAPS, WRITE, struct_dmx_caps_sz);
149 _(DMX_SET_SOURCE, READ, enum_dmx_source_sz);
150 /* Entries from file: dev/dtv/dtvio_frontend.h */
151 _(FE_READ_STATUS, WRITE, enum_fe_status_sz);
152 _(FE_READ_BER, WRITE, sizeof(u32));
153 _(FE_READ_SNR, WRITE, sizeof(u16));
154 _(FE_READ_SIGNAL_STRENGTH, WRITE, sizeof(u16));
155 _(FE_READ_UNCORRECTED_BLOCKS, WRITE, sizeof(u32));
156 _(FE_SET_FRONTEND, READWRITE, struct_dvb_frontend_parameters_sz);
157 _(FE_GET_FRONTEND, WRITE, struct_dvb_frontend_parameters_sz);
158 _(FE_GET_EVENT, WRITE, struct_dvb_frontend_event_sz);
159 _(FE_GET_INFO, WRITE, struct_dvb_frontend_info_sz);
160 _(FE_DISEQC_RESET_OVERLOAD, NONE, 0);
161 _(FE_DISEQC_SEND_MASTER_CMD, READ, struct_dvb_diseqc_master_cmd_sz);
162 _(FE_DISEQC_RECV_SLAVE_REPLY, WRITE, struct_dvb_diseqc_slave_reply_sz);
163 _(FE_DISEQC_SEND_BURST, READ, enum_fe_sec_mini_cmd_sz);
164 _(FE_SET_TONE, READ, enum_fe_sec_tone_mode_sz);
165 _(FE_SET_VOLTAGE, READ, enum_fe_sec_voltage_sz);
166 _(FE_ENABLE_HIGH_LNB_VOLTAGE, READ, sizeof(int));
167 _(FE_SET_FRONTEND_TUNE_MODE, READ, sizeof(unsigned int));
168 _(FE_DISHNETWORK_SEND_LEGACY_CMD, READ, sizeof(unsigned long));
169 /* Entries from file: dev/hdaudio/hdaudioio.h */
170 _(HDAUDIO_FGRP_INFO, READWRITE, struct_plistref_sz);
171 _(HDAUDIO_FGRP_GETCONFIG, READWRITE, struct_plistref_sz);
172 _(HDAUDIO_FGRP_SETCONFIG, READWRITE, struct_plistref_sz);
173 _(HDAUDIO_FGRP_WIDGET_INFO, READWRITE, struct_plistref_sz);
174 _(HDAUDIO_FGRP_CODEC_INFO, READWRITE, struct_plistref_sz);
175 _(HDAUDIO_AFG_WIDGET_INFO, READWRITE, struct_plistref_sz);
176 _(HDAUDIO_AFG_CODEC_INFO, READWRITE, struct_plistref_sz);
177 /* Entries from file: dev/hdmicec/hdmicecio.h */
178 _(CEC_GET_PHYS_ADDR, WRITE, sizeof(u16));
179 _(CEC_GET_LOG_ADDRS, WRITE, sizeof(u16));
180 _(CEC_SET_LOG_ADDRS, READ, sizeof(u16));
181 _(CEC_GET_VENDOR_ID, WRITE, sizeof(u32));
182 /* Entries from file: dev/hpc/hpcfbio.h */
183 _(HPCFBIO_GCONF, READWRITE, struct_hpcfb_fbconf_sz);
184 _(HPCFBIO_SCONF, READ, struct_hpcfb_fbconf_sz);
185 _(HPCFBIO_GDSPCONF, READWRITE, struct_hpcfb_dspconf_sz);
186 _(HPCFBIO_SDSPCONF, READ, struct_hpcfb_dspconf_sz);
187 _(HPCFBIO_GOP, WRITE, struct_hpcfb_dsp_op_sz);
188 _(HPCFBIO_SOP, READWRITE, struct_hpcfb_dsp_op_sz);
189 /* Entries from file: dev/i2o/iopio.h */
190 _(IOPIOCPT, READWRITE, struct_ioppt_sz);
191 _(IOPIOCGLCT, READWRITE, struct_iovec_sz);
192 _(IOPIOCGSTATUS, READWRITE, struct_iovec_sz);
193 _(IOPIOCRECONFIG, NONE, 0);
194 _(IOPIOCGTIDMAP, READWRITE, struct_iovec_sz);
195 /* Entries from file: dev/ic/athioctl.h */
196 _(SIOCGATHSTATS, READWRITE, struct_ifreq_sz);
197 _(SIOCGATHDIAG, READWRITE, struct_ath_diag_sz);
198 /* Entries from file: dev/ic/bt8xx.h */
199 _(METEORCAPTUR, READ, sizeof(int));
200 _(METEORCAPFRM, READ, struct_meteor_capframe_sz);
201 _(METEORSETGEO, READ, struct_meteor_geomet_sz);
202 _(METEORGETGEO, WRITE, struct_meteor_geomet_sz);
203 _(METEORSTATUS, WRITE, sizeof(unsigned short));
204 _(METEORSHUE, READ, sizeof(signed char));
205 _(METEORGHUE, WRITE, sizeof(signed char));
206 _(METEORSFMT, READ, sizeof(unsigned int));
207 _(METEORGFMT, WRITE, sizeof(unsigned int));
208 _(METEORSINPUT, READ, sizeof(unsigned int));
209 _(METEORGINPUT, WRITE, sizeof(unsigned int));
210 _(METEORSCHCV, READ, sizeof(unsigned char));
211 _(METEORGCHCV, WRITE, sizeof(unsigned char));
212 _(METEORSCOUNT, READ, struct_meteor_counts_sz);
213 _(METEORGCOUNT, WRITE, struct_meteor_counts_sz);
214 _(METEORSFPS, READ, sizeof(unsigned short));
215 _(METEORGFPS, WRITE, sizeof(unsigned short));
216 _(METEORSSIGNAL, READ, sizeof(unsigned int));
217 _(METEORGSIGNAL, WRITE, sizeof(unsigned int));
218 _(METEORSVIDEO, READ, struct_meteor_video_sz);
219 _(METEORGVIDEO, WRITE, struct_meteor_video_sz);
220 _(METEORSBRIG, READ, sizeof(unsigned char));
221 _(METEORGBRIG, WRITE, sizeof(unsigned char));
222 _(METEORSCSAT, READ, sizeof(unsigned char));
223 _(METEORGCSAT, WRITE, sizeof(unsigned char));
224 _(METEORSCONT, READ, sizeof(unsigned char));
225 _(METEORGCONT, WRITE, sizeof(unsigned char));
226 _(METEORSHWS, READ, sizeof(unsigned char));
227 _(METEORGHWS, WRITE, sizeof(unsigned char));
228 _(METEORSVWS, READ, sizeof(unsigned char));
229 _(METEORGVWS, WRITE, sizeof(unsigned char));
230 _(METEORSTS, READ, sizeof(unsigned char));
231 _(METEORGTS, WRITE, sizeof(unsigned char));
232 _(TVTUNER_SETCHNL, READ, sizeof(unsigned int));
233 _(TVTUNER_GETCHNL, WRITE, sizeof(unsigned int));
234 _(TVTUNER_SETTYPE, READ, sizeof(unsigned int));
235 _(TVTUNER_GETTYPE, WRITE, sizeof(unsigned int));
236 _(TVTUNER_GETSTATUS, WRITE, sizeof(unsigned int));
237 _(TVTUNER_SETFREQ, READ, sizeof(unsigned int));
238 _(TVTUNER_GETFREQ, WRITE, sizeof(unsigned int));
239 _(TVTUNER_SETAFC, READ, sizeof(int));
240 _(TVTUNER_GETAFC, WRITE, sizeof(int));
241 _(RADIO_SETMODE, READ, sizeof(unsigned int));
242 _(RADIO_GETMODE, WRITE, sizeof(unsigned char));
243 _(RADIO_SETFREQ, READ, sizeof(unsigned int));
244 _(RADIO_GETFREQ, WRITE, sizeof(unsigned int));
245 _(METEORSACTPIXFMT, READ, sizeof(int));
246 _(METEORGACTPIXFMT, WRITE, sizeof(int));
247 _(METEORGSUPPIXFMT, READWRITE, struct_meteor_pixfmt_sz);
248 _(TVTUNER_GETCHNLSET, READWRITE, struct_bktr_chnlset_sz);
249 _(REMOTE_GETKEY, WRITE, struct_bktr_remote_sz);
250 /* Entries from file: dev/ic/icp_ioctl.h */
251 _(GDT_IOCTL_GENERAL, READWRITE, struct_gdt_ucmd_sz);
252 _(GDT_IOCTL_DRVERS, WRITE, sizeof(int));
253 _(GDT_IOCTL_CTRTYPE, READWRITE, struct_gdt_ctrt_sz);
254 _(GDT_IOCTL_OSVERS, WRITE, struct_gdt_osv_sz);
255 _(GDT_IOCTL_CTRCNT, WRITE, sizeof(int));
256 _(GDT_IOCTL_EVENT, READWRITE, struct_gdt_event_sz);
257 _(GDT_IOCTL_STATIST, WRITE, struct_gdt_statist_sz);
258 _(GDT_IOCTL_RESCAN, READWRITE, struct_gdt_rescan_sz);
259 /* Entries from file: dev/ic/isp_ioctl.h */
260 _(ISP_SDBLEV, READWRITE, sizeof(int));
261 _(ISP_RESETHBA, NONE, 0);
262 _(ISP_RESCAN, NONE, 0);
263 _(ISP_SETROLE, READWRITE, sizeof(int));
264 _(ISP_GETROLE, WRITE, sizeof(int));
265 _(ISP_GET_STATS, WRITE, struct_isp_stats_sz);
266 _(ISP_CLR_STATS, NONE, 0);
267 _(ISP_FC_LIP, NONE, 0);
268 _(ISP_FC_GETDINFO, READWRITE, struct_isp_fc_device_sz);
269 _(ISP_GET_FW_CRASH_DUMP, NONE, 0);
270 _(ISP_FORCE_CRASH_DUMP, NONE, 0);
271 _(ISP_FC_GETHINFO, READWRITE, struct_isp_hba_device_sz);
272 _(ISP_TSK_MGMT, READWRITE, struct_isp_fc_tsk_mgmt_sz);
273 _(ISP_FC_GETDLIST, NONE, 0);
274 /* Entries from file: dev/ic/mlxio.h */
275 _(MLXD_STATUS, WRITE, sizeof(int));
276 _(MLXD_CHECKASYNC, WRITE, sizeof(int));
277 _(MLXD_DETACH, READ, sizeof(int));
278 _(MLX_RESCAN_DRIVES, NONE, 0);
279 _(MLX_PAUSE_CHANNEL, READ, struct_mlx_pause_sz);
280 _(MLX_COMMAND, READWRITE, struct_mlx_usercommand_sz);
281 _(MLX_REBUILDASYNC, READWRITE, struct_mlx_rebuild_request_sz);
282 _(MLX_REBUILDSTAT, WRITE, struct_mlx_rebuild_status_sz);
283 _(MLX_GET_SYSDRIVE, READWRITE, sizeof(int));
284 _(MLX_GET_CINFO, WRITE, struct_mlx_cinfo_sz);
285 /* Entries from file: dev/ic/nvmeio.h */
286 _(NVME_PASSTHROUGH_CMD, READWRITE, struct_nvme_pt_command_sz);
287 /* Entries from file: dev/ic/qemufwcfgio.h */
288 _(FWCFGIO_SET_INDEX, READ, sizeof(u16));
289 /* Entries from file: dev/ir/irdaio.h */
290 _(IRDA_RESET_PARAMS, NONE, 0);
291 _(IRDA_SET_PARAMS, READ, struct_irda_params_sz);
292 _(IRDA_GET_SPEEDMASK, WRITE, sizeof(unsigned int));
293 _(IRDA_GET_TURNAROUNDMASK, WRITE, sizeof(unsigned int));
294 _(IRFRAMETTY_GET_DEVICE, WRITE, sizeof(unsigned int));
295 _(IRFRAMETTY_GET_DONGLE, WRITE, sizeof(unsigned int));
296 _(IRFRAMETTY_SET_DONGLE, READ, sizeof(unsigned int));
297 /* Entries from file: dev/isa/isvio.h */
298 _(ISV_CMD, READWRITE, struct_isv_cmd_sz);
299 /* Entries from file: dev/isa/wtreg.h */
300 _(WTQICMD, NONE, 0);
301 /* Entries from file: dev/iscsi/iscsi_ioctl.h */
302 _(ISCSI_GET_VERSION, READWRITE, struct_iscsi_get_version_parameters_sz);
303 _(ISCSI_LOGIN, READWRITE, struct_iscsi_login_parameters_sz);
304 _(ISCSI_LOGOUT, READWRITE, struct_iscsi_logout_parameters_sz);
305 _(ISCSI_ADD_CONNECTION, READWRITE, struct_iscsi_login_parameters_sz);
306 _(ISCSI_RESTORE_CONNECTION, READWRITE, struct_iscsi_login_parameters_sz);
307 _(ISCSI_REMOVE_CONNECTION, READWRITE, struct_iscsi_remove_parameters_sz);
308 _(ISCSI_CONNECTION_STATUS, READWRITE, struct_iscsi_conn_status_parameters_sz);
309 _(ISCSI_SEND_TARGETS, READWRITE, struct_iscsi_send_targets_parameters_sz);
310 _(ISCSI_SET_NODE_NAME, READWRITE, struct_iscsi_set_node_name_parameters_sz);
311 _(ISCSI_IO_COMMAND, READWRITE, struct_iscsi_iocommand_parameters_sz);
312 _(ISCSI_REGISTER_EVENT, READWRITE, struct_iscsi_register_event_parameters_sz);
313 _(ISCSI_DEREGISTER_EVENT, READWRITE,
314 struct_iscsi_register_event_parameters_sz);
315 _(ISCSI_WAIT_EVENT, READWRITE, struct_iscsi_wait_event_parameters_sz);
316 _(ISCSI_POLL_EVENT, READWRITE, struct_iscsi_wait_event_parameters_sz);
317 /* Entries from file: dev/ofw/openfirmio.h */
318 _(OFIOCGET, READWRITE, struct_ofiocdesc_sz);
319 _(OFIOCSET, READ, struct_ofiocdesc_sz);
320 _(OFIOCNEXTPROP, READWRITE, struct_ofiocdesc_sz);
321 _(OFIOCGETOPTNODE, WRITE, sizeof(int));
322 _(OFIOCGETNEXT, READWRITE, sizeof(int));
323 _(OFIOCGETCHILD, READWRITE, sizeof(int));
324 _(OFIOCFINDDEVICE, READWRITE, struct_ofiocdesc_sz);
325 /* Entries from file: dev/pci/amrio.h */
326 _(AMR_IO_VERSION, WRITE, sizeof(int));
327 _(AMR_IO_COMMAND, READWRITE, struct_amr_user_ioctl_sz);
328 /* Entries from file: dev/pci/mlyio.h */
329 _(MLYIO_COMMAND, READWRITE, struct_mly_user_command_sz);
330 _(MLYIO_HEALTH, READ, struct_mly_user_health_sz);
331 /* Entries from file: dev/pci/pciio.h */
332 _(PCI_IOC_CFGREAD, READWRITE, struct_pciio_cfgreg_sz);
333 _(PCI_IOC_CFGWRITE, READ, struct_pciio_cfgreg_sz);
334 _(PCI_IOC_BDF_CFGREAD, READWRITE, struct_pciio_bdf_cfgreg_sz);
335 _(PCI_IOC_BDF_CFGWRITE, READ, struct_pciio_bdf_cfgreg_sz);
336 _(PCI_IOC_BUSINFO, WRITE, struct_pciio_businfo_sz);
337 _(PCI_IOC_DRVNAME, READWRITE, struct_pciio_drvname_sz);
338 _(PCI_IOC_DRVNAMEONBUS, READWRITE, struct_pciio_drvnameonbus_sz);
339 /* Entries from file: dev/pci/tweio.h */
340 _(TWEIO_COMMAND, READWRITE, struct_twe_usercommand_sz);
341 _(TWEIO_STATS, READWRITE, union_twe_statrequest_sz);
342 _(TWEIO_AEN_POLL, WRITE, sizeof(int));
343 _(TWEIO_AEN_WAIT, WRITE, sizeof(int));
344 _(TWEIO_SET_PARAM, READ, struct_twe_paramcommand_sz);
345 _(TWEIO_GET_PARAM, READ, struct_twe_paramcommand_sz);
346 _(TWEIO_RESET, NONE, 0);
347 _(TWEIO_ADD_UNIT, READ, struct_twe_drivecommand_sz);
348 _(TWEIO_DEL_UNIT, READ, struct_twe_drivecommand_sz);
349 /* Entries from file: dev/pcmcia/if_cnwioctl.h */
350 _(SIOCSCNWDOMAIN, READ, struct_ifreq_sz);
351 _(SIOCGCNWDOMAIN, READWRITE, struct_ifreq_sz);
352 _(SIOCSCNWKEY, READWRITE, struct_ifreq_sz);
353 _(SIOCGCNWSTATUS, READWRITE, struct_cnwstatus_sz);
354 _(SIOCGCNWSTATS, READWRITE, struct_cnwistats_sz);
355 _(SIOCGCNWTRAIL, READWRITE, struct_cnwitrail_sz);
356 /* Entries from file: dev/pcmcia/if_rayreg.h */
357 _(SIOCGRAYSIGLEV, READWRITE, struct_ifreq_sz);
358 /* Entries from file: dev/raidframe/raidframeio.h */
359 _(RAIDFRAME_SHUTDOWN, NONE, 0);
360 _(RAIDFRAME_TUR, READ, sizeof(u64));
361 _(RAIDFRAME_FAIL_DISK, READ, struct_rf_recon_req_sz);
362 _(RAIDFRAME_CHECK_RECON_STATUS, READWRITE, sizeof(int));
363 _(RAIDFRAME_REWRITEPARITY, NONE, 0);
364 _(RAIDFRAME_COPYBACK, NONE, 0);
365 _(RAIDFRAME_SPARET_WAIT, WRITE, struct_RF_SparetWait_sz);
366 _(RAIDFRAME_SEND_SPARET, READ, sizeof(uptr));
367 _(RAIDFRAME_ABORT_SPARET_WAIT, NONE, 0);
368 _(RAIDFRAME_START_ATRACE, NONE, 0);
369 _(RAIDFRAME_STOP_ATRACE, NONE, 0);
370 _(RAIDFRAME_GET_SIZE, WRITE, sizeof(int));
371 _(RAIDFRAME_RESET_ACCTOTALS, NONE, 0);
372 _(RAIDFRAME_KEEP_ACCTOTALS, READ, sizeof(int));
373 _(RAIDFRAME_GET_COMPONENT_LABEL, READWRITE, struct_RF_ComponentLabel_sz);
374 _(RAIDFRAME_SET_COMPONENT_LABEL, READ, struct_RF_ComponentLabel_sz);
375 _(RAIDFRAME_INIT_LABELS, READ, struct_RF_ComponentLabel_sz);
376 _(RAIDFRAME_ADD_HOT_SPARE, READ, struct_RF_SingleComponent_sz);
377 _(RAIDFRAME_REMOVE_HOT_SPARE, READ, struct_RF_SingleComponent_sz);
378 _(RAIDFRAME_REBUILD_IN_PLACE, READ, struct_RF_SingleComponent_sz);
379 _(RAIDFRAME_CHECK_PARITY, READWRITE, sizeof(int));
380 _(RAIDFRAME_CHECK_PARITYREWRITE_STATUS, READWRITE, sizeof(int));
381 _(RAIDFRAME_CHECK_COPYBACK_STATUS, READWRITE, sizeof(int));
382 _(RAIDFRAME_SET_AUTOCONFIG, READWRITE, sizeof(int));
383 _(RAIDFRAME_SET_ROOT, READWRITE, sizeof(int));
384 _(RAIDFRAME_DELETE_COMPONENT, READ, struct_RF_SingleComponent_sz);
385 _(RAIDFRAME_INCORPORATE_HOT_SPARE, READ, struct_RF_SingleComponent_sz);
386 _(RAIDFRAME_CHECK_RECON_STATUS_EXT, READWRITE, struct_RF_ProgressInfo_sz);
387 _(RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT, READWRITE,
388 struct_RF_ProgressInfo_sz);
389 _(RAIDFRAME_CHECK_COPYBACK_STATUS_EXT, READWRITE, struct_RF_ProgressInfo_sz);
390 _(RAIDFRAME_PARITYMAP_STATUS, WRITE, struct_rf_pmstat_sz);
391 _(RAIDFRAME_PARITYMAP_GET_DISABLE, WRITE, sizeof(int));
392 _(RAIDFRAME_PARITYMAP_SET_DISABLE, READ, sizeof(int));
393 _(RAIDFRAME_PARITYMAP_SET_PARAMS, READ, struct_rf_pmparams_sz);
394 _(RAIDFRAME_SET_LAST_UNIT, READ, sizeof(int));
395 _(RAIDFRAME_GET_INFO, READWRITE, sizeof(uptr));
396 _(RAIDFRAME_CONFIGURE, READ, sizeof(uptr));
397 /* Entries from file: dev/sbus/mbppio.h */
398 _(MBPPIOCSPARAM, READ, struct_mbpp_param_sz);
399 _(MBPPIOCGPARAM, WRITE, struct_mbpp_param_sz);
400 _(MBPPIOCGSTAT, WRITE, sizeof(int));
401 /* Entries from file: dev/scsipi/ses.h */
402 _(SESIOC_GETNOBJ, NONE, 0);
403 _(SESIOC_GETOBJMAP, NONE, 0);
404 _(SESIOC_GETENCSTAT, NONE, 0);
405 _(SESIOC_SETENCSTAT, NONE, 0);
406 _(SESIOC_GETOBJSTAT, NONE, 0);
407 _(SESIOC_SETOBJSTAT, NONE, 0);
408 _(SESIOC_GETTEXT, NONE, 0);
409 _(SESIOC_INIT, NONE, 0);
410 /* Entries from file: dev/sun/disklabel.h */
411 _(SUN_DKIOCGGEOM, WRITE, struct_sun_dkgeom_sz);
412 _(SUN_DKIOCINFO, WRITE, struct_sun_dkctlr_sz);
413 _(SUN_DKIOCGPART, WRITE, struct_sun_dkpart_sz);
414 /* Entries from file: dev/sun/fbio.h */
415 _(FBIOGTYPE, WRITE, struct_fbtype_sz);
416 _(FBIOPUTCMAP, READ, struct_fbcmap_sz);
417 _(FBIOGETCMAP, READ, struct_fbcmap_sz);
418 _(FBIOGATTR, WRITE, struct_fbgattr_sz);
419 _(FBIOSVIDEO, READ, sizeof(int));
420 _(FBIOGVIDEO, WRITE, sizeof(int));
421 _(FBIOSCURSOR, READ, struct_fbcursor_sz);
422 _(FBIOGCURSOR, READWRITE, struct_fbcursor_sz);
423 _(FBIOSCURPOS, READ, struct_fbcurpos_sz);
424 _(FBIOGCURPOS, READ, struct_fbcurpos_sz);
425 _(FBIOGCURMAX, WRITE, struct_fbcurpos_sz);
426 /* Entries from file: dev/sun/kbio.h */
427 _(KIOCTRANS, READ, sizeof(int));
428 _(KIOCSETKEY, READWRITE, struct_okiockey_sz);
429 _(KIOCGETKEY, READWRITE, struct_okiockey_sz);
430 _(KIOCGTRANS, WRITE, sizeof(int));
431 _(KIOCCMD, READ, sizeof(int));
432 _(KIOCTYPE, WRITE, sizeof(int));
433 _(KIOCSDIRECT, READ, sizeof(int));
434 _(KIOCSKEY, READ, struct_kiockeymap_sz);
435 _(KIOCGKEY, READWRITE, struct_kiockeymap_sz);
436 _(KIOCSLED, READ, sizeof(char));
437 _(KIOCGLED, WRITE, sizeof(char));
438 _(KIOCLAYOUT, WRITE, sizeof(int));
439 /* Entries from file: dev/sun/vuid_event.h */
440 _(VUIDSFORMAT, READ, sizeof(int));
441 _(VUIDGFORMAT, WRITE, sizeof(int));
442 /* Entries from file: dev/tc/sticio.h */
443 _(STICIO_GXINFO, WRITE, struct_stic_xinfo_sz);
444 _(STICIO_RESET, NONE, 0);
445 _(STICIO_STARTQ, NONE, 0);
446 _(STICIO_STOPQ, NONE, 0);
447 /* Entries from file: dev/usb/ukyopon.h */
448 _(UKYOPON_IDENTIFY, WRITE, struct_ukyopon_identify_sz);
449 /* Entries from file: dev/usb/usb.h */
450 _(USB_REQUEST, READWRITE, struct_usb_ctl_request_sz);
451 _(USB_SETDEBUG, READ, sizeof(int));
452 _(USB_DISCOVER, NONE, 0);
453 _(USB_DEVICEINFO, READWRITE, struct_usb_device_info_sz);
454 _(USB_DEVICEINFO_OLD, READWRITE, struct_usb_device_info_old_sz);
455 _(USB_DEVICESTATS, WRITE, struct_usb_device_stats_sz);
456 _(USB_GET_REPORT_DESC, WRITE, struct_usb_ctl_report_desc_sz);
457 _(USB_SET_IMMED, READ, sizeof(int));
458 _(USB_GET_REPORT, READWRITE, struct_usb_ctl_report_sz);
459 _(USB_SET_REPORT, READ, struct_usb_ctl_report_sz);
460 _(USB_GET_REPORT_ID, WRITE, sizeof(int));
461 _(USB_GET_CONFIG, WRITE, sizeof(int));
462 _(USB_SET_CONFIG, READ, sizeof(int));
463 _(USB_GET_ALTINTERFACE, READWRITE, struct_usb_alt_interface_sz);
464 _(USB_SET_ALTINTERFACE, READWRITE, struct_usb_alt_interface_sz);
465 _(USB_GET_NO_ALT, READWRITE, struct_usb_alt_interface_sz);
466 _(USB_GET_DEVICE_DESC, WRITE, struct_usb_device_descriptor_sz);
467 _(USB_GET_CONFIG_DESC, READWRITE, struct_usb_config_desc_sz);
468 _(USB_GET_INTERFACE_DESC, READWRITE, struct_usb_interface_desc_sz);
469 _(USB_GET_ENDPOINT_DESC, READWRITE, struct_usb_endpoint_desc_sz);
470 _(USB_GET_FULL_DESC, READWRITE, struct_usb_full_desc_sz);
471 _(USB_GET_STRING_DESC, READWRITE, struct_usb_string_desc_sz);
472 _(USB_DO_REQUEST, READWRITE, struct_usb_ctl_request_sz);
473 _(USB_GET_DEVICEINFO, WRITE, struct_usb_device_info_sz);
474 _(USB_GET_DEVICEINFO_OLD, WRITE, struct_usb_device_info_old_sz);
475 _(USB_SET_SHORT_XFER, READ, sizeof(int));
476 _(USB_SET_TIMEOUT, READ, sizeof(int));
477 _(USB_SET_BULK_RA, READ, sizeof(int));
478 _(USB_SET_BULK_WB, READ, sizeof(int));
479 _(USB_SET_BULK_RA_OPT, READ, struct_usb_bulk_ra_wb_opt_sz);
480 _(USB_SET_BULK_WB_OPT, READ, struct_usb_bulk_ra_wb_opt_sz);
481 _(USB_GET_CM_OVER_DATA, WRITE, sizeof(int));
482 _(USB_SET_CM_OVER_DATA, READ, sizeof(int));
483 /* Entries from file: dev/usb/utoppy.h */
484 _(UTOPPYIOTURBO, READ, sizeof(int));
485 _(UTOPPYIOREBOOT, NONE, 0);
486 _(UTOPPYIOSTATS, WRITE, struct_utoppy_stats_sz);
487 _(UTOPPYIORENAME, READ, struct_utoppy_rename_sz);
488 _(UTOPPYIOMKDIR, READ, sizeof(uptr));
489 _(UTOPPYIODELETE, READ, sizeof(uptr));
490 _(UTOPPYIOREADDIR, READ, sizeof(uptr));
491 _(UTOPPYIOREADFILE, READ, struct_utoppy_readfile_sz);
492 _(UTOPPYIOWRITEFILE, READ, struct_utoppy_writefile_sz);
493 /* Entries from file: dev/vme/xio.h */
494 _(DIOSXDCMD, READWRITE, struct_xd_iocmd_sz);
495 /* Entries from file: dev/wscons/wsdisplay_usl_io.h */
496 _(VT_OPENQRY, WRITE, sizeof(int));
497 _(VT_SETMODE, READ, struct_vt_mode_sz);
498 _(VT_GETMODE, WRITE, struct_vt_mode_sz);
499 _(VT_RELDISP, NONE, 0);
500 _(VT_ACTIVATE, NONE, 0);
501 _(VT_WAITACTIVE, NONE, 0);
502 _(VT_GETACTIVE, WRITE, sizeof(int));
503 _(VT_GETSTATE, WRITE, struct_vt_stat_sz);
504 _(KDGETKBENT, READWRITE, struct_kbentry_sz);
505 _(KDGKBMODE, WRITE, sizeof(int));
506 _(KDSKBMODE, NONE, 0);
507 _(KDMKTONE, NONE, 0);
508 _(KDSETMODE, NONE, 0);
509 _(KDENABIO, NONE, 0);
510 _(KDDISABIO, NONE, 0);
511 _(KDGKBTYPE, WRITE, sizeof(char));
512 _(KDGETLED, WRITE, sizeof(int));
513 _(KDSETLED, NONE, 0);
514 _(KDSETRAD, NONE, 0);
515 _(VGAPCVTID, READWRITE, struct_pcvtid_sz);
516 _(CONS_GETVERS, WRITE, sizeof(int));
517 /* Entries from file: dev/wscons/wsconsio.h */
518 _(WSKBDIO_GTYPE, WRITE, sizeof(unsigned int));
519 _(WSKBDIO_BELL, NONE, 0);
520 _(WSKBDIO_COMPLEXBELL, READ, struct_wskbd_bell_data_sz);
521 _(WSKBDIO_SETBELL, READ, struct_wskbd_bell_data_sz);
522 _(WSKBDIO_GETBELL, WRITE, struct_wskbd_bell_data_sz);
523 _(WSKBDIO_SETDEFAULTBELL, READ, struct_wskbd_bell_data_sz);
524 _(WSKBDIO_GETDEFAULTBELL, WRITE, struct_wskbd_bell_data_sz);
525 _(WSKBDIO_SETKEYREPEAT, READ, struct_wskbd_keyrepeat_data_sz);
526 _(WSKBDIO_GETKEYREPEAT, WRITE, struct_wskbd_keyrepeat_data_sz);
527 _(WSKBDIO_SETDEFAULTKEYREPEAT, READ, struct_wskbd_keyrepeat_data_sz);
528 _(WSKBDIO_GETDEFAULTKEYREPEAT, WRITE, struct_wskbd_keyrepeat_data_sz);
529 _(WSKBDIO_SETLEDS, READ, sizeof(int));
530 _(WSKBDIO_GETLEDS, WRITE, sizeof(int));
531 _(WSKBDIO_GETMAP, READWRITE, struct_wskbd_map_data_sz);
532 _(WSKBDIO_SETMAP, READ, struct_wskbd_map_data_sz);
533 _(WSKBDIO_GETENCODING, WRITE, sizeof(int));
534 _(WSKBDIO_SETENCODING, READ, sizeof(int));
535 _(WSKBDIO_SETMODE, READ, sizeof(int));
536 _(WSKBDIO_GETMODE, WRITE, sizeof(int));
537 _(WSKBDIO_SETKEYCLICK, READ, sizeof(int));
538 _(WSKBDIO_GETKEYCLICK, WRITE, sizeof(int));
539 _(WSKBDIO_GETSCROLL, WRITE, struct_wskbd_scroll_data_sz);
540 _(WSKBDIO_SETSCROLL, READ, struct_wskbd_scroll_data_sz);
541 _(WSKBDIO_SETVERSION, READ, sizeof(int));
542 _(WSMOUSEIO_GTYPE, WRITE, sizeof(unsigned int));
543 _(WSMOUSEIO_SRES, READ, sizeof(unsigned int));
544 _(WSMOUSEIO_SSCALE, READ, sizeof(unsigned int));
545 _(WSMOUSEIO_SRATE, READ, sizeof(unsigned int));
546 _(WSMOUSEIO_SCALIBCOORDS, READ, struct_wsmouse_calibcoords_sz);
547 _(WSMOUSEIO_GCALIBCOORDS, WRITE, struct_wsmouse_calibcoords_sz);
548 _(WSMOUSEIO_GETID, READWRITE, struct_wsmouse_id_sz);
549 _(WSMOUSEIO_GETREPEAT, WRITE, struct_wsmouse_repeat_sz);
550 _(WSMOUSEIO_SETREPEAT, READ, struct_wsmouse_repeat_sz);
551 _(WSMOUSEIO_SETVERSION, READ, sizeof(int));
552 _(WSDISPLAYIO_GTYPE, WRITE, sizeof(unsigned int));
553 _(WSDISPLAYIO_GINFO, WRITE, struct_wsdisplay_fbinfo_sz);
554 _(WSDISPLAYIO_GETCMAP, READ, struct_wsdisplay_cmap_sz);
555 _(WSDISPLAYIO_PUTCMAP, READ, struct_wsdisplay_cmap_sz);
556 _(WSDISPLAYIO_GVIDEO, WRITE, sizeof(unsigned int));
557 _(WSDISPLAYIO_SVIDEO, READ, sizeof(unsigned int));
558 _(WSDISPLAYIO_GCURPOS, WRITE, struct_wsdisplay_curpos_sz);
559 _(WSDISPLAYIO_SCURPOS, READ, struct_wsdisplay_curpos_sz);
560 _(WSDISPLAYIO_GCURMAX, WRITE, struct_wsdisplay_curpos_sz);
561 _(WSDISPLAYIO_GCURSOR, READWRITE, struct_wsdisplay_cursor_sz);
562 _(WSDISPLAYIO_SCURSOR, READ, struct_wsdisplay_cursor_sz);
563 _(WSDISPLAYIO_GMODE, WRITE, sizeof(unsigned int));
564 _(WSDISPLAYIO_SMODE, READ, sizeof(unsigned int));
565 _(WSDISPLAYIO_LDFONT, READ, struct_wsdisplay_font_sz);
566 _(WSDISPLAYIO_ADDSCREEN, READ, struct_wsdisplay_addscreendata_sz);
567 _(WSDISPLAYIO_DELSCREEN, READ, struct_wsdisplay_delscreendata_sz);
568 _(WSDISPLAYIO_SFONT, READ, struct_wsdisplay_usefontdata_sz);
569 _(_O_WSDISPLAYIO_SETKEYBOARD, READWRITE, struct_wsdisplay_kbddata_sz);
570 _(WSDISPLAYIO_GETPARAM, READWRITE, struct_wsdisplay_param_sz);
571 _(WSDISPLAYIO_SETPARAM, READWRITE, struct_wsdisplay_param_sz);
572 _(WSDISPLAYIO_GETACTIVESCREEN, WRITE, sizeof(int));
573 _(WSDISPLAYIO_GETWSCHAR, READWRITE, struct_wsdisplay_char_sz);
574 _(WSDISPLAYIO_PUTWSCHAR, READWRITE, struct_wsdisplay_char_sz);
575 _(WSDISPLAYIO_DGSCROLL, WRITE, struct_wsdisplay_scroll_data_sz);
576 _(WSDISPLAYIO_DSSCROLL, READ, struct_wsdisplay_scroll_data_sz);
577 _(WSDISPLAYIO_GMSGATTRS, WRITE, struct_wsdisplay_msgattrs_sz);
578 _(WSDISPLAYIO_SMSGATTRS, READ, struct_wsdisplay_msgattrs_sz);
579 _(WSDISPLAYIO_GBORDER, WRITE, sizeof(int));
580 _(WSDISPLAYIO_SBORDER, READ, sizeof(int));
581 _(WSDISPLAYIO_SSPLASH, READ, sizeof(int));
582 _(WSDISPLAYIO_SPROGRESS, READ, sizeof(int));
583 _(WSDISPLAYIO_LINEBYTES, WRITE, sizeof(unsigned int));
584 _(WSDISPLAYIO_SETVERSION, READ, sizeof(int));
585 _(WSMUXIO_ADD_DEVICE, READ, struct_wsmux_device_sz);
586 _(WSMUXIO_REMOVE_DEVICE, READ, struct_wsmux_device_sz);
587 _(WSMUXIO_LIST_DEVICES, READWRITE, struct_wsmux_device_list_sz);
588 _(WSMUXIO_INJECTEVENT, READ, struct_wscons_event_sz);
589 _(WSDISPLAYIO_GET_BUSID, WRITE, struct_wsdisplayio_bus_id_sz);
590 _(WSDISPLAYIO_GET_EDID, READWRITE, struct_wsdisplayio_edid_info_sz);
591 _(WSDISPLAYIO_SET_POLLING, READ, sizeof(int));
592 _(WSDISPLAYIO_GET_FBINFO, READWRITE, struct_wsdisplayio_fbinfo_sz);
593 _(WSDISPLAYIO_DOBLIT, READWRITE, struct_wsdisplayio_blit_sz);
594 _(WSDISPLAYIO_WAITBLIT, READWRITE, struct_wsdisplayio_blit_sz);
595 /* Entries from file: dev/biovar.h */
596 _(BIOCLOCATE, READWRITE, struct_bio_locate_sz);
597 _(BIOCINQ, READWRITE, struct_bioc_inq_sz);
598 _(BIOCDISK_NOVOL, READWRITE, struct_bioc_disk_sz);
599 _(BIOCDISK, READWRITE, struct_bioc_disk_sz);
600 _(BIOCVOL, READWRITE, struct_bioc_vol_sz);
601 _(BIOCALARM, READWRITE, struct_bioc_alarm_sz);
602 _(BIOCBLINK, READWRITE, struct_bioc_blink_sz);
603 _(BIOCSETSTATE, READWRITE, struct_bioc_setstate_sz);
604 _(BIOCVOLOPS, READWRITE, struct_bioc_volops_sz);
605 /* Entries from file: dev/md.h */
606 _(MD_GETCONF, WRITE, struct_md_conf_sz);
607 _(MD_SETCONF, READ, struct_md_conf_sz);
608 /* Entries from file: dev/ccdvar.h */
609 _(CCDIOCSET, READWRITE, struct_ccd_ioctl_sz);
610 _(CCDIOCCLR, READ, struct_ccd_ioctl_sz);
611 /* Entries from file: dev/cgdvar.h */
612 _(CGDIOCSET, READWRITE, struct_cgd_ioctl_sz);
613 _(CGDIOCCLR, READ, struct_cgd_ioctl_sz);
614 _(CGDIOCGET, READWRITE, struct_cgd_user_sz);
615 /* Entries from file: dev/fssvar.h */
616 _(FSSIOCSET, READ, struct_fss_set_sz);
617 _(FSSIOCGET, WRITE, struct_fss_get_sz);
618 _(FSSIOCCLR, NONE, 0);
619 _(FSSIOFSET, READ, sizeof(int));
620 _(FSSIOFGET, WRITE, sizeof(int));
621 /* Entries from file: dev/bluetooth/btdev.h */
622 _(BTDEV_ATTACH, READ, struct_plistref_sz);
623 _(BTDEV_DETACH, READ, struct_plistref_sz);
624 /* Entries from file: dev/bluetooth/btsco.h */
625 _(BTSCO_GETINFO, WRITE, struct_btsco_info_sz);
626 /* Entries from file: dev/kttcpio.h */
627 _(KTTCP_IO_SEND, READWRITE, struct_kttcp_io_args_sz);
628 _(KTTCP_IO_RECV, READWRITE, struct_kttcp_io_args_sz);
629 /* Entries from file: dev/lockstat.h */
630 _(IOC_LOCKSTAT_GVERSION, WRITE, sizeof(int));
631 _(IOC_LOCKSTAT_ENABLE, READ, struct_lsenable_sz);
632 _(IOC_LOCKSTAT_DISABLE, WRITE, struct_lsdisable_sz);
633 /* Entries from file: dev/vndvar.h */
634 _(VNDIOCSET, READWRITE, struct_vnd_ioctl_sz);
635 _(VNDIOCCLR, READ, struct_vnd_ioctl_sz);
636 _(VNDIOCGET, READWRITE, struct_vnd_user_sz);
637 /* Entries from file: dev/spkrio.h */
638 _(SPKRTONE, READ, struct_tone_sz);
639 _(SPKRTUNE, NONE, 0);
640 _(SPKRGETVOL, WRITE, sizeof(unsigned int));
641 _(SPKRSETVOL, READ, sizeof(unsigned int));
642#if defined(__x86_64__)
643 /* Entries from file: dev/nvmm/nvmm_ioctl.h */
644 _(NVMM_IOC_CAPABILITY, WRITE, struct_nvmm_ioc_capability_sz);
645 _(NVMM_IOC_MACHINE_CREATE, READWRITE, struct_nvmm_ioc_machine_create_sz);
646 _(NVMM_IOC_MACHINE_DESTROY, READ, struct_nvmm_ioc_machine_destroy_sz);
647 _(NVMM_IOC_MACHINE_CONFIGURE, READ, struct_nvmm_ioc_machine_configure_sz);
648 _(NVMM_IOC_VCPU_CREATE, READ, struct_nvmm_ioc_vcpu_create_sz);
649 _(NVMM_IOC_VCPU_DESTROY, READ, struct_nvmm_ioc_vcpu_destroy_sz);
650 _(NVMM_IOC_VCPU_CONFIGURE, READ, struct_nvmm_ioc_vcpu_configure_sz);
651 _(NVMM_IOC_VCPU_SETSTATE, READ, struct_nvmm_ioc_vcpu_setstate_sz);
652 _(NVMM_IOC_VCPU_GETSTATE, READ, struct_nvmm_ioc_vcpu_getstate_sz);
653 _(NVMM_IOC_VCPU_INJECT, READ, struct_nvmm_ioc_vcpu_inject_sz);
654 _(NVMM_IOC_VCPU_RUN, READWRITE, struct_nvmm_ioc_vcpu_run_sz);
655 _(NVMM_IOC_GPA_MAP, READ, struct_nvmm_ioc_gpa_map_sz);
656 _(NVMM_IOC_GPA_UNMAP, READ, struct_nvmm_ioc_gpa_unmap_sz);
657 _(NVMM_IOC_HVA_MAP, READ, struct_nvmm_ioc_hva_map_sz);
658 _(NVMM_IOC_HVA_UNMAP, READ, struct_nvmm_ioc_hva_unmap_sz);
659 _(NVMM_IOC_CTL, READ, struct_nvmm_ioc_ctl_sz);
660#endif
661 /* Entries from file: dev/spi/spi_io.h */
662 _(SPI_IOCTL_CONFIGURE, READ, struct_spi_ioctl_configure_sz);
663 _(SPI_IOCTL_TRANSFER, READ, struct_spi_ioctl_transfer_sz);
664 /* Entries from file: fs/autofs/autofs_ioctl.h */
665 _(AUTOFSREQUEST, WRITE, struct_autofs_daemon_request_sz);
666 _(AUTOFSDONE, READ, struct_autofs_daemon_done_sz);
667 /* Entries from file: net/bpf.h */
668 _(BIOCGBLEN, WRITE, sizeof(unsigned int));
669 _(BIOCSBLEN, READWRITE, sizeof(unsigned int));
670 _(BIOCSETF, READ, struct_bpf_program_sz);
671 _(BIOCFLUSH, NONE, 0);
672 _(BIOCPROMISC, NONE, 0);
673 _(BIOCGDLT, WRITE, sizeof(unsigned int));
674 _(BIOCGETIF, WRITE, struct_ifreq_sz);
675 _(BIOCSETIF, READ, struct_ifreq_sz);
676 _(BIOCGSTATS, WRITE, struct_bpf_stat_sz);
677 _(BIOCGSTATSOLD, WRITE, struct_bpf_stat_old_sz);
678 _(BIOCIMMEDIATE, READ, sizeof(unsigned int));
679 _(BIOCVERSION, WRITE, struct_bpf_version_sz);
680 _(BIOCSTCPF, READ, struct_bpf_program_sz);
681 _(BIOCSUDPF, READ, struct_bpf_program_sz);
682 _(BIOCGHDRCMPLT, WRITE, sizeof(unsigned int));
683 _(BIOCSHDRCMPLT, READ, sizeof(unsigned int));
684 _(BIOCSDLT, READ, sizeof(unsigned int));
685 _(BIOCGDLTLIST, READWRITE, struct_bpf_dltlist_sz);
686 _(BIOCGDIRECTION, WRITE, sizeof(unsigned int));
687 _(BIOCSDIRECTION, READ, sizeof(unsigned int));
688 _(BIOCSRTIMEOUT, READ, struct_timeval_sz);
689 _(BIOCGRTIMEOUT, WRITE, struct_timeval_sz);
690 _(BIOCGFEEDBACK, WRITE, sizeof(unsigned int));
691 _(BIOCSFEEDBACK, READ, sizeof(unsigned int));
692 /* Entries from file: net/if_gre.h */
693 _(GRESADDRS, READ, struct_ifreq_sz);
694 _(GRESADDRD, READ, struct_ifreq_sz);
695 _(GREGADDRS, READWRITE, struct_ifreq_sz);
696 _(GREGADDRD, READWRITE, struct_ifreq_sz);
697 _(GRESPROTO, READ, struct_ifreq_sz);
698 _(GREGPROTO, READWRITE, struct_ifreq_sz);
699 _(GRESSOCK, READ, struct_ifreq_sz);
700 _(GREDSOCK, READ, struct_ifreq_sz);
701 /* Entries from file: net/if_ppp.h */
702 _(PPPIOCGRAWIN, WRITE, struct_ppp_rawin_sz);
703 _(PPPIOCGFLAGS, WRITE, sizeof(int));
704 _(PPPIOCSFLAGS, READ, sizeof(int));
705 _(PPPIOCGASYNCMAP, WRITE, sizeof(int));
706 _(PPPIOCSASYNCMAP, READ, sizeof(int));
707 _(PPPIOCGUNIT, WRITE, sizeof(int));
708 _(PPPIOCGRASYNCMAP, WRITE, sizeof(int));
709 _(PPPIOCSRASYNCMAP, READ, sizeof(int));
710 _(PPPIOCGMRU, WRITE, sizeof(int));
711 _(PPPIOCSMRU, READ, sizeof(int));
712 _(PPPIOCSMAXCID, READ, sizeof(int));
713 _(PPPIOCGXASYNCMAP, WRITE, (8 * sizeof(u32)));
714 _(PPPIOCSXASYNCMAP, READ, (8 * sizeof(u32)));
715 _(PPPIOCXFERUNIT, NONE, 0);
716 _(PPPIOCSCOMPRESS, READ, struct_ppp_option_data_sz);
717 _(PPPIOCGNPMODE, READWRITE, struct_npioctl_sz);
718 _(PPPIOCSNPMODE, READ, struct_npioctl_sz);
719 _(PPPIOCGIDLE, WRITE, struct_ppp_idle_sz);
720 _(PPPIOCGMTU, WRITE, sizeof(int));
721 _(PPPIOCSMTU, READ, sizeof(int));
722 _(SIOCGPPPSTATS, READWRITE, struct_ifpppstatsreq_sz);
723 _(SIOCGPPPCSTATS, READWRITE, struct_ifpppcstatsreq_sz);
724 /* Entries from file: net/npf.h */
725 _(IOC_NPF_VERSION, WRITE, sizeof(int));
726 _(IOC_NPF_SWITCH, READ, sizeof(int));
727 _(IOC_NPF_LOAD, READWRITE, struct_nvlist_ref_sz);
728 _(IOC_NPF_TABLE, READ, struct_npf_ioctl_table_sz);
729 _(IOC_NPF_STATS, READ, sizeof(uptr));
730 _(IOC_NPF_SAVE, WRITE, struct_nvlist_ref_sz);
731 _(IOC_NPF_RULE, READWRITE, struct_nvlist_ref_sz);
732 _(IOC_NPF_CONN_LOOKUP, READWRITE, struct_nvlist_ref_sz);
733 _(IOC_NPF_TABLE_REPLACE, READWRITE, struct_nvlist_ref_sz);
734 /* Entries from file: net/if_pppoe.h */
735 _(PPPOESETPARMS, READ, struct_pppoediscparms_sz);
736 _(PPPOEGETPARMS, READWRITE, struct_pppoediscparms_sz);
737 _(PPPOEGETSESSION, READWRITE, struct_pppoeconnectionstate_sz);
738 /* Entries from file: net/if_sppp.h */
739 _(SPPPGETAUTHCFG, READWRITE, struct_spppauthcfg_sz);
740 _(SPPPSETAUTHCFG, READ, struct_spppauthcfg_sz);
741 _(SPPPGETLCPCFG, READWRITE, struct_sppplcpcfg_sz);
742 _(SPPPSETLCPCFG, READ, struct_sppplcpcfg_sz);
743 _(SPPPGETSTATUS, READWRITE, struct_spppstatus_sz);
744 _(SPPPGETSTATUSNCP, READWRITE, struct_spppstatusncp_sz);
745 _(SPPPGETIDLETO, READWRITE, struct_spppidletimeout_sz);
746 _(SPPPSETIDLETO, READ, struct_spppidletimeout_sz);
747 _(SPPPGETAUTHFAILURES, READWRITE, struct_spppauthfailurestats_sz);
748 _(SPPPSETAUTHFAILURE, READ, struct_spppauthfailuresettings_sz);
749 _(SPPPSETDNSOPTS, READ, struct_spppdnssettings_sz);
750 _(SPPPGETDNSOPTS, READWRITE, struct_spppdnssettings_sz);
751 _(SPPPGETDNSADDRS, READWRITE, struct_spppdnsaddrs_sz);
752 _(SPPPSETKEEPALIVE, READ, struct_spppkeepalivesettings_sz);
753 _(SPPPGETKEEPALIVE, READWRITE, struct_spppkeepalivesettings_sz);
754 /* Entries from file: net/if_srt.h */
755 _(SRT_GETNRT, WRITE, sizeof(unsigned int));
756 _(SRT_GETRT, READWRITE, struct_srt_rt_sz);
757 _(SRT_SETRT, READ, struct_srt_rt_sz);
758 _(SRT_DELRT, READ, sizeof(unsigned int));
759 _(SRT_SFLAGS, READ, sizeof(unsigned int));
760 _(SRT_GFLAGS, WRITE, sizeof(unsigned int));
761 _(SRT_SGFLAGS, READWRITE, sizeof(unsigned int));
762 _(SRT_DEBUG, READ, sizeof(uptr));
763 /* Entries from file: net/if_tap.h */
764 _(TAPGIFNAME, WRITE, struct_ifreq_sz);
765 /* Entries from file: net/if_tun.h */
766 _(TUNSDEBUG, READ, sizeof(int));
767 _(TUNGDEBUG, WRITE, sizeof(int));
768 _(TUNSIFMODE, READ, sizeof(int));
769 _(TUNSIFHEAD, READ, sizeof(int));
770 _(TUNGIFHEAD, WRITE, sizeof(int));
771 /* Entries from file: net/pfvar.h */
772 _(DIOCSTART, NONE, 0);
773 _(DIOCSTOP, NONE, 0);
774 _(DIOCADDRULE, READWRITE, struct_pfioc_rule_sz);
775 _(DIOCGETRULES, READWRITE, struct_pfioc_rule_sz);
776 _(DIOCGETRULE, READWRITE, struct_pfioc_rule_sz);
777 _(DIOCSETLCK, READWRITE, sizeof(u32));
778 _(DIOCCLRSTATES, READWRITE, struct_pfioc_state_kill_sz);
779 _(DIOCGETSTATE, READWRITE, struct_pfioc_state_sz);
780 _(DIOCSETSTATUSIF, READWRITE, struct_pfioc_if_sz);
781 _(DIOCGETSTATUS, READWRITE, struct_pf_status_sz);
782 _(DIOCCLRSTATUS, NONE, 0);
783 _(DIOCNATLOOK, READWRITE, struct_pfioc_natlook_sz);
784 _(DIOCSETDEBUG, READWRITE, sizeof(u32));
785 _(DIOCGETSTATES, READWRITE, struct_pfioc_states_sz);
786 _(DIOCCHANGERULE, READWRITE, struct_pfioc_rule_sz);
787 _(DIOCSETTIMEOUT, READWRITE, struct_pfioc_tm_sz);
788 _(DIOCGETTIMEOUT, READWRITE, struct_pfioc_tm_sz);
789 _(DIOCADDSTATE, READWRITE, struct_pfioc_state_sz);
790 _(DIOCCLRRULECTRS, NONE, 0);
791 _(DIOCGETLIMIT, READWRITE, struct_pfioc_limit_sz);
792 _(DIOCSETLIMIT, READWRITE, struct_pfioc_limit_sz);
793 _(DIOCKILLSTATES, READWRITE, struct_pfioc_state_kill_sz);
794 _(DIOCSTARTALTQ, NONE, 0);
795 _(DIOCSTOPALTQ, NONE, 0);
796 _(DIOCADDALTQ, READWRITE, struct_pfioc_altq_sz);
797 _(DIOCGETALTQS, READWRITE, struct_pfioc_altq_sz);
798 _(DIOCGETALTQ, READWRITE, struct_pfioc_altq_sz);
799 _(DIOCCHANGEALTQ, READWRITE, struct_pfioc_altq_sz);
800 _(DIOCGETQSTATS, READWRITE, struct_pfioc_qstats_sz);
801 _(DIOCBEGINADDRS, READWRITE, struct_pfioc_pooladdr_sz);
802 _(DIOCADDADDR, READWRITE, struct_pfioc_pooladdr_sz);
803 _(DIOCGETADDRS, READWRITE, struct_pfioc_pooladdr_sz);
804 _(DIOCGETADDR, READWRITE, struct_pfioc_pooladdr_sz);
805 _(DIOCCHANGEADDR, READWRITE, struct_pfioc_pooladdr_sz);
806 _(DIOCADDSTATES, READWRITE, struct_pfioc_states_sz);
807 _(DIOCGETRULESETS, READWRITE, struct_pfioc_ruleset_sz);
808 _(DIOCGETRULESET, READWRITE, struct_pfioc_ruleset_sz);
809 _(DIOCRCLRTABLES, READWRITE, struct_pfioc_table_sz);
810 _(DIOCRADDTABLES, READWRITE, struct_pfioc_table_sz);
811 _(DIOCRDELTABLES, READWRITE, struct_pfioc_table_sz);
812 _(DIOCRGETTABLES, READWRITE, struct_pfioc_table_sz);
813 _(DIOCRGETTSTATS, READWRITE, struct_pfioc_table_sz);
814 _(DIOCRCLRTSTATS, READWRITE, struct_pfioc_table_sz);
815 _(DIOCRCLRADDRS, READWRITE, struct_pfioc_table_sz);
816 _(DIOCRADDADDRS, READWRITE, struct_pfioc_table_sz);
817 _(DIOCRDELADDRS, READWRITE, struct_pfioc_table_sz);
818 _(DIOCRSETADDRS, READWRITE, struct_pfioc_table_sz);
819 _(DIOCRGETADDRS, READWRITE, struct_pfioc_table_sz);
820 _(DIOCRGETASTATS, READWRITE, struct_pfioc_table_sz);
821 _(DIOCRCLRASTATS, READWRITE, struct_pfioc_table_sz);
822 _(DIOCRTSTADDRS, READWRITE, struct_pfioc_table_sz);
823 _(DIOCRSETTFLAGS, READWRITE, struct_pfioc_table_sz);
824 _(DIOCRINADEFINE, READWRITE, struct_pfioc_table_sz);
825 _(DIOCOSFPFLUSH, NONE, 0);
826 _(DIOCOSFPADD, READWRITE, struct_pf_osfp_ioctl_sz);
827 _(DIOCOSFPGET, READWRITE, struct_pf_osfp_ioctl_sz);
828 _(DIOCXBEGIN, READWRITE, struct_pfioc_trans_sz);
829 _(DIOCXCOMMIT, READWRITE, struct_pfioc_trans_sz);
830 _(DIOCXROLLBACK, READWRITE, struct_pfioc_trans_sz);
831 _(DIOCGETSRCNODES, READWRITE, struct_pfioc_src_nodes_sz);
832 _(DIOCCLRSRCNODES, NONE, 0);
833 _(DIOCSETHOSTID, READWRITE, sizeof(u32));
834 _(DIOCIGETIFACES, READWRITE, struct_pfioc_iface_sz);
835 _(DIOCSETIFFLAG, READWRITE, struct_pfioc_iface_sz);
836 _(DIOCCLRIFFLAG, READWRITE, struct_pfioc_iface_sz);
837 _(DIOCKILLSRCNODES, READWRITE, struct_pfioc_src_node_kill_sz);
838 /* Entries from file: netbt/hci.h */
839 _(SIOCGBTINFO, READWRITE, struct_btreq_sz);
840 _(SIOCGBTINFOA, READWRITE, struct_btreq_sz);
841 _(SIOCNBTINFO, READWRITE, struct_btreq_sz);
842 _(SIOCSBTFLAGS, READWRITE, struct_btreq_sz);
843 _(SIOCSBTPOLICY, READWRITE, struct_btreq_sz);
844 _(SIOCSBTPTYPE, READWRITE, struct_btreq_sz);
845 _(SIOCGBTSTATS, READWRITE, struct_btreq_sz);
846 _(SIOCZBTSTATS, READWRITE, struct_btreq_sz);
847 _(SIOCBTDUMP, READ, struct_btreq_sz);
848 _(SIOCSBTSCOMTU, READWRITE, struct_btreq_sz);
849 _(SIOCGBTFEAT, READWRITE, struct_btreq_sz);
850 /* Entries from file: netinet/ip_nat.h */
851 _(SIOCADNAT, READ, struct_ipfobj_sz);
852 _(SIOCRMNAT, READ, struct_ipfobj_sz);
853 _(SIOCGNATS, READWRITE, struct_ipfobj_sz);
854 _(SIOCGNATL, READWRITE, struct_ipfobj_sz);
855 _(SIOCPURGENAT, READWRITE, struct_ipfobj_sz);
856 /* Entries from file: netinet/sctp_uio.h */
857 _(SIOCCONNECTX, READWRITE, struct_sctp_connectx_addrs_sz);
858 _(SIOCCONNECTXDEL, READWRITE, struct_sctp_connectx_addrs_sz);
859 /* Entries from file: netinet6/in6_var.h */
860 _(SIOCSIFINFO_FLAGS, READWRITE, struct_in6_ndireq_sz);
861 _(SIOCAADDRCTL_POLICY, READ, struct_in6_addrpolicy_sz);
862 _(SIOCDADDRCTL_POLICY, READ, struct_in6_addrpolicy_sz);
863 /* Entries from file: netsmb/smb_dev.h */
864 _(SMBIOC_OPENSESSION, READ, struct_smbioc_ossn_sz);
865 _(SMBIOC_OPENSHARE, READ, struct_smbioc_oshare_sz);
866 _(SMBIOC_REQUEST, READWRITE, struct_smbioc_rq_sz);
867 _(SMBIOC_SETFLAGS, READ, struct_smbioc_flags_sz);
868 _(SMBIOC_LOOKUP, READ, struct_smbioc_lookup_sz);
869 _(SMBIOC_READ, READWRITE, struct_smbioc_rw_sz);
870 _(SMBIOC_WRITE, READWRITE, struct_smbioc_rw_sz);
871 /* Entries from file: sys/agpio.h */
872 _(AGPIOC_INFO, WRITE, struct__agp_info_sz);
873 _(AGPIOC_ACQUIRE, NONE, 0);
874 _(AGPIOC_RELEASE, NONE, 0);
875 _(AGPIOC_SETUP, READ, struct__agp_setup_sz);
876 _(AGPIOC_ALLOCATE, READWRITE, struct__agp_allocate_sz);
877 _(AGPIOC_DEALLOCATE, READ, sizeof(int));
878 _(AGPIOC_BIND, READ, struct__agp_bind_sz);
879 _(AGPIOC_UNBIND, READ, struct__agp_unbind_sz);
880 /* Entries from file: sys/audioio.h */
881 _(AUDIO_GETINFO, WRITE, struct_audio_info_sz);
882 _(AUDIO_SETINFO, READWRITE, struct_audio_info_sz);
883 _(AUDIO_DRAIN, NONE, 0);
884 _(AUDIO_FLUSH, NONE, 0);
885 _(AUDIO_WSEEK, WRITE, sizeof(unsigned long));
886 _(AUDIO_RERROR, WRITE, sizeof(int));
887 _(AUDIO_GETDEV, WRITE, struct_audio_device_sz);
888 _(AUDIO_GETENC, READWRITE, struct_audio_encoding_sz);
889 _(AUDIO_GETFD, WRITE, sizeof(int));
890 _(AUDIO_SETFD, READWRITE, sizeof(int));
891 _(AUDIO_PERROR, WRITE, sizeof(int));
892 _(AUDIO_GETIOFFS, WRITE, struct_audio_offset_sz);
893 _(AUDIO_GETOOFFS, WRITE, struct_audio_offset_sz);
894 _(AUDIO_GETPROPS, WRITE, sizeof(int));
895 _(AUDIO_GETBUFINFO, WRITE, struct_audio_info_sz);
896 _(AUDIO_SETCHAN, READ, sizeof(int));
897 _(AUDIO_GETCHAN, WRITE, sizeof(int));
898 _(AUDIO_QUERYFORMAT, READWRITE, struct_audio_format_query_sz);
899 _(AUDIO_GETFORMAT, WRITE, struct_audio_info_sz);
900 _(AUDIO_SETFORMAT, READ, struct_audio_info_sz);
901 _(AUDIO_MIXER_READ, READWRITE, struct_mixer_ctrl_sz);
902 _(AUDIO_MIXER_WRITE, READWRITE, struct_mixer_ctrl_sz);
903 _(AUDIO_MIXER_DEVINFO, READWRITE, struct_mixer_devinfo_sz);
904 /* Entries from file: sys/ataio.h */
905 _(ATAIOCCOMMAND, READWRITE, struct_atareq_sz);
906 _(ATABUSIOSCAN, READ, struct_atabusioscan_args_sz);
907 _(ATABUSIORESET, NONE, 0);
908 _(ATABUSIODETACH, READ, struct_atabusiodetach_args_sz);
909 /* Entries from file: sys/cdio.h */
910 _(CDIOCPLAYTRACKS, READ, struct_ioc_play_track_sz);
911 _(CDIOCPLAYBLOCKS, READ, struct_ioc_play_blocks_sz);
912 _(CDIOCREADSUBCHANNEL, READWRITE, struct_ioc_read_subchannel_sz);
913 _(CDIOREADTOCHEADER, WRITE, struct_ioc_toc_header_sz);
914 _(CDIOREADTOCENTRIES, READWRITE, struct_ioc_read_toc_entry_sz);
915 _(CDIOREADMSADDR, READWRITE, sizeof(int));
916 _(CDIOCSETPATCH, READ, struct_ioc_patch_sz);
917 _(CDIOCGETVOL, WRITE, struct_ioc_vol_sz);
918 _(CDIOCSETVOL, READ, struct_ioc_vol_sz);
919 _(CDIOCSETMONO, NONE, 0);
920 _(CDIOCSETSTEREO, NONE, 0);
921 _(CDIOCSETMUTE, NONE, 0);
922 _(CDIOCSETLEFT, NONE, 0);
923 _(CDIOCSETRIGHT, NONE, 0);
924 _(CDIOCSETDEBUG, NONE, 0);
925 _(CDIOCCLRDEBUG, NONE, 0);
926 _(CDIOCPAUSE, NONE, 0);
927 _(CDIOCRESUME, NONE, 0);
928 _(CDIOCRESET, NONE, 0);
929 _(CDIOCSTART, NONE, 0);
930 _(CDIOCSTOP, NONE, 0);
931 _(CDIOCEJECT, NONE, 0);
932 _(CDIOCALLOW, NONE, 0);
933 _(CDIOCPREVENT, NONE, 0);
934 _(CDIOCCLOSE, NONE, 0);
935 _(CDIOCPLAYMSF, READ, struct_ioc_play_msf_sz);
936 _(CDIOCLOADUNLOAD, READ, struct_ioc_load_unload_sz);
937 /* Entries from file: sys/chio.h */
938 _(CHIOMOVE, READ, struct_changer_move_request_sz);
939 _(CHIOEXCHANGE, READ, struct_changer_exchange_request_sz);
940 _(CHIOPOSITION, READ, struct_changer_position_request_sz);
941 _(CHIOSPICKER, READ, sizeof(int));
942 _(CHIOGPARAMS, WRITE, struct_changer_params_sz);
943 _(CHIOIELEM, NONE, 0);
944 _(OCHIOGSTATUS, READ, struct_ochanger_element_status_request_sz);
945 _(CHIOGSTATUS, READ, struct_changer_element_status_request_sz);
946 _(CHIOSVOLTAG, READ, struct_changer_set_voltag_request_sz);
947 /* Entries from file: sys/clockctl.h */
948 _(CLOCKCTL_SETTIMEOFDAY, READ, struct_clockctl_settimeofday_sz);
949 _(CLOCKCTL_ADJTIME, READWRITE, struct_clockctl_adjtime_sz);
950 _(CLOCKCTL_CLOCK_SETTIME, READ, struct_clockctl_clock_settime_sz);
951 _(CLOCKCTL_NTP_ADJTIME, READWRITE, struct_clockctl_ntp_adjtime_sz);
952 /* Entries from file: sys/cpuio.h */
953 _(IOC_CPU_SETSTATE, READ, struct_cpustate_sz);
954 _(IOC_CPU_GETSTATE, READWRITE, struct_cpustate_sz);
955 _(IOC_CPU_GETCOUNT, WRITE, sizeof(int));
956 _(IOC_CPU_MAPID, READWRITE, sizeof(int));
957 _(IOC_CPU_UCODE_GET_VERSION, READWRITE, struct_cpu_ucode_version_sz);
958 _(IOC_CPU_UCODE_APPLY, READ, struct_cpu_ucode_sz);
959 /* Entries from file: sys/dkio.h */
960 _(DIOCGDINFO, WRITE, struct_disklabel_sz);
961 _(DIOCSDINFO, READ, struct_disklabel_sz);
962 _(DIOCWDINFO, READ, 0);
963 _(DIOCRFORMAT, READWRITE, struct_format_op_sz);
964 _(DIOCWFORMAT, READWRITE, struct_format_op_sz);
965 _(DIOCSSTEP, READ, sizeof(int));
966 _(DIOCSRETRIES, READ, sizeof(int));
967 _(DIOCKLABEL, READ, sizeof(int));
968 _(DIOCWLABEL, READ, sizeof(int));
969 _(DIOCSBAD, READ, struct_dkbad_sz);
970 _(DIOCEJECT, READ, sizeof(int));
971 _(ODIOCEJECT, NONE, 0);
972 _(DIOCLOCK, READ, sizeof(int));
973 _(DIOCGDEFLABEL, WRITE, struct_disklabel_sz);
974 _(DIOCCLRLABEL, NONE, 0);
975 _(DIOCGCACHE, WRITE, sizeof(int));
976 _(DIOCSCACHE, READ, sizeof(int));
977 _(DIOCCACHESYNC, READ, sizeof(int));
978 _(DIOCBSLIST, READWRITE, struct_disk_badsecinfo_sz);
979 _(DIOCBSFLUSH, NONE, 0);
980 _(DIOCAWEDGE, READWRITE, struct_dkwedge_info_sz);
981 _(DIOCGWEDGEINFO, WRITE, struct_dkwedge_info_sz);
982 _(DIOCDWEDGE, READ, struct_dkwedge_info_sz);
983 _(DIOCLWEDGES, READWRITE, struct_dkwedge_list_sz);
984 _(DIOCGSTRATEGY, WRITE, struct_disk_strategy_sz);
985 _(DIOCSSTRATEGY, READ, struct_disk_strategy_sz);
986 _(DIOCGDISKINFO, WRITE, struct_plistref_sz);
987 _(DIOCTUR, WRITE, sizeof(int));
988 _(DIOCMWEDGES, WRITE, sizeof(int));
989 _(DIOCGSECTORSIZE, WRITE, sizeof(unsigned int));
990 _(DIOCGMEDIASIZE, WRITE, sizeof(uptr));
991 _(DIOCRMWEDGES, WRITE, sizeof(int));
992 /* Entries from file: sys/drvctlio.h */
993 _(DRVDETACHDEV, READ, struct_devdetachargs_sz);
994 _(DRVRESCANBUS, READ, struct_devrescanargs_sz);
995 _(DRVCTLCOMMAND, READWRITE, struct_plistref_sz);
996 _(DRVRESUMEDEV, READ, struct_devpmargs_sz);
997 _(DRVLISTDEV, READWRITE, struct_devlistargs_sz);
998 _(DRVGETEVENT, WRITE, struct_plistref_sz);
999 _(DRVSUSPENDDEV, READ, struct_devpmargs_sz);
1000 /* Entries from file: sys/dvdio.h */
1001 _(DVD_READ_STRUCT, READWRITE, union_dvd_struct_sz);
1002 _(DVD_WRITE_STRUCT, READWRITE, union_dvd_struct_sz);
1003 _(DVD_AUTH, READWRITE, union_dvd_authinfo_sz);
1004 /* Entries from file: sys/envsys.h */
1005 _(ENVSYS_GETDICTIONARY, READWRITE, struct_plistref_sz);
1006 _(ENVSYS_SETDICTIONARY, READWRITE, struct_plistref_sz);
1007 _(ENVSYS_REMOVEPROPS, READWRITE, struct_plistref_sz);
1008 _(ENVSYS_GTREDATA, READWRITE, struct_envsys_tre_data_sz);
1009 _(ENVSYS_GTREINFO, READWRITE, struct_envsys_basic_info_sz);
1010 /* Entries from file: sys/event.h */
1011 _(KFILTER_BYFILTER, READWRITE, struct_kfilter_mapping_sz);
1012 _(KFILTER_BYNAME, READWRITE, struct_kfilter_mapping_sz);
1013 /* Entries from file: sys/fdio.h */
1014 _(FDIOCGETOPTS, WRITE, 0);
1015 _(FDIOCSETOPTS, READ, sizeof(int));
1016 _(FDIOCSETFORMAT, READ, struct_fdformat_parms_sz);
1017 _(FDIOCGETFORMAT, WRITE, struct_fdformat_parms_sz);
1018 _(FDIOCFORMAT_TRACK, READ, struct_fdformat_cmd_sz);
1019 /* Entries from file: sys/filio.h */
1020 _(FIOCLEX, NONE, 0);
1021 _(FIONCLEX, NONE, 0);
1022 _(FIOSEEKDATA, READWRITE, sizeof(uptr));
1023 _(FIOSEEKHOLE, READWRITE, sizeof(uptr));
1024 _(FIONREAD, WRITE, sizeof(int));
1025 _(FIONBIO, READ, sizeof(int));
1026 _(FIOASYNC, READ, sizeof(int));
1027 _(FIOSETOWN, READ, sizeof(int));
1028 _(FIOGETOWN, WRITE, sizeof(int));
1029 _(OFIOGETBMAP, READWRITE, sizeof(u32));
1030 _(FIOGETBMAP, READWRITE, sizeof(u64));
1031 _(FIONWRITE, WRITE, sizeof(int));
1032 _(FIONSPACE, WRITE, sizeof(int));
1033 /* Entries from file: sys/gpio.h */
1034 _(GPIOINFO, WRITE, struct_gpio_info_sz);
1035 _(GPIOSET, READWRITE, struct_gpio_set_sz);
1036 _(GPIOUNSET, READWRITE, struct_gpio_set_sz);
1037 _(GPIOREAD, READWRITE, struct_gpio_req_sz);
1038 _(GPIOWRITE, READWRITE, struct_gpio_req_sz);
1039 _(GPIOTOGGLE, READWRITE, struct_gpio_req_sz);
1040 _(GPIOATTACH, READWRITE, struct_gpio_attach_sz);
1041 /* Entries from file: sys/ioctl.h */
1042 _(PTIOCNETBSD, READ, struct_ioctl_pt_sz);
1043 _(PTIOCSUNOS, READ, struct_ioctl_pt_sz);
1044 _(PTIOCLINUX, READ, struct_ioctl_pt_sz);
1045 _(PTIOCFREEBSD, READ, struct_ioctl_pt_sz);
1046 _(PTIOCULTRIX, READ, struct_ioctl_pt_sz);
1047 /* Entries from file: sys/ioctl_compat.h */
1048 _(TIOCHPCL, NONE, 0);
1049 _(TIOCGETP, WRITE, struct_sgttyb_sz);
1050 _(TIOCSETP, READ, struct_sgttyb_sz);
1051 _(TIOCSETN, READ, 0);
1052 _(TIOCSETC, READ, struct_tchars_sz);
1053 _(TIOCGETC, WRITE, struct_tchars_sz);
1054 _(TIOCLBIS, READ, sizeof(int));
1055 _(TIOCLBIC, READ, sizeof(int));
1056 _(TIOCLSET, READ, sizeof(int));
1057 _(TIOCLGET, WRITE, sizeof(int));
1058 _(TIOCSLTC, READ, struct_ltchars_sz);
1059 _(TIOCGLTC, WRITE, struct_ltchars_sz);
1060 _(OTIOCCONS, NONE, 0);
1061 /* Entries from file: sys/joystick.h */
1062 _(JOY_SETTIMEOUT, READ, sizeof(int));
1063 _(JOY_GETTIMEOUT, WRITE, sizeof(int));
1064 _(JOY_SET_X_OFFSET, READ, sizeof(int));
1065 _(JOY_SET_Y_OFFSET, READ, sizeof(int));
1066 _(JOY_GET_Y_OFFSET, WRITE, sizeof(int));
1067 /* Entries from file: sys/ksyms.h */
1068 _(OKIOCGSYMBOL, READ, struct_ksyms_ogsymbol_sz);
1069 _(OKIOCGVALUE, READ, struct_ksyms_ogsymbol_sz);
1070 _(KIOCGSIZE, WRITE, sizeof(int));
1071 _(KIOCGVALUE, READWRITE, struct_ksyms_gvalue_sz);
1072 _(KIOCGSYMBOL, READWRITE, struct_ksyms_gsymbol_sz);
1073 /* Entries from file: sys/lua.h */
1074 _(LUAINFO, READWRITE, struct_lua_info_sz);
1075 _(LUACREATE, READWRITE, struct_lua_create_sz);
1076 _(LUADESTROY, READWRITE, struct_lua_create_sz);
1077 _(LUAREQUIRE, READWRITE, struct_lua_require_sz);
1078 _(LUALOAD, READWRITE, struct_lua_load_sz);
1079 /* Entries from file: sys/midiio.h */
1080 _(MIDI_PRETIME, READWRITE, sizeof(int));
1081 _(MIDI_MPUMODE, READWRITE, sizeof(int));
1082 _(MIDI_MPUCMD, READWRITE, struct_mpu_command_rec_sz);
1083 _(SEQUENCER_RESET, NONE, 0);
1084 _(SEQUENCER_SYNC, NONE, 0);
1085 _(SEQUENCER_INFO, READWRITE, struct_synth_info_sz);
1086 _(SEQUENCER_CTRLRATE, READWRITE, sizeof(int));
1087 _(SEQUENCER_GETOUTCOUNT, WRITE, sizeof(int));
1088 _(SEQUENCER_GETINCOUNT, WRITE, sizeof(int));
1089 _(SEQUENCER_RESETSAMPLES, READ, sizeof(int));
1090 _(SEQUENCER_NRSYNTHS, WRITE, sizeof(int));
1091 _(SEQUENCER_NRMIDIS, WRITE, sizeof(int));
1092 _(SEQUENCER_THRESHOLD, READ, sizeof(int));
1093 _(SEQUENCER_MEMAVL, READWRITE, sizeof(int));
1094 _(SEQUENCER_PANIC, NONE, 0);
1095 _(SEQUENCER_OUTOFBAND, READ, struct_seq_event_rec_sz);
1096 _(SEQUENCER_GETTIME, WRITE, sizeof(int));
1097 _(SEQUENCER_TMR_TIMEBASE, READWRITE, sizeof(int));
1098 _(SEQUENCER_TMR_START, NONE, 0);
1099 _(SEQUENCER_TMR_STOP, NONE, 0);
1100 _(SEQUENCER_TMR_CONTINUE, NONE, 0);
1101 _(SEQUENCER_TMR_TEMPO, READWRITE, sizeof(int));
1102 _(SEQUENCER_TMR_SOURCE, READWRITE, sizeof(int));
1103 _(SEQUENCER_TMR_METRONOME, READ, sizeof(int));
1104 _(SEQUENCER_TMR_SELECT, READ, sizeof(int));
1105 /* Entries from file: sys/mtio.h */
1106 _(MTIOCTOP, READ, struct_mtop_sz);
1107 _(MTIOCGET, WRITE, struct_mtget_sz);
1108 _(MTIOCIEOT, NONE, 0);
1109 _(MTIOCEEOT, NONE, 0);
1110 _(MTIOCRDSPOS, WRITE, sizeof(u32));
1111 _(MTIOCRDHPOS, WRITE, sizeof(u32));
1112 _(MTIOCSLOCATE, READ, sizeof(u32));
1113 _(MTIOCHLOCATE, READ, sizeof(u32));
1114 /* Entries from file: sys/power.h */
1115 _(POWER_EVENT_RECVDICT, READWRITE, struct_plistref_sz);
1116 _(POWER_IOC_GET_TYPE, WRITE, struct_power_type_sz);
1117 /* Entries from file: sys/radioio.h */
1118 _(RIOCGINFO, WRITE, struct_radio_info_sz);
1119 _(RIOCSINFO, READWRITE, struct_radio_info_sz);
1120 _(RIOCSSRCH, READ, sizeof(int));
1121 /* Entries from file: sys/rndio.h */
1122 _(RNDGETENTCNT, WRITE, sizeof(u32));
1123 _(RNDGETSRCNUM, READWRITE, struct_rndstat_sz);
1124 _(RNDGETSRCNAME, READWRITE, struct_rndstat_name_sz);
1125 _(RNDCTL, READ, struct_rndctl_sz);
1126 _(RNDADDDATA, READ, struct_rnddata_sz);
1127 _(RNDGETPOOLSTAT, WRITE, struct_rndpoolstat_sz);
1128 _(RNDGETESTNUM, READWRITE, struct_rndstat_est_sz);
1129 _(RNDGETESTNAME, READWRITE, struct_rndstat_est_name_sz);
1130 /* Entries from file: sys/scanio.h */
1131 _(SCIOCGET, WRITE, struct_scan_io_sz);
1132 _(SCIOCSET, READ, struct_scan_io_sz);
1133 _(SCIOCRESTART, NONE, 0);
1134 /* Entries from file: sys/scsiio.h */
1135 _(SCIOCCOMMAND, READWRITE, struct_scsireq_sz);
1136 _(SCIOCDEBUG, READ, sizeof(int));
1137 _(SCIOCIDENTIFY, WRITE, struct_scsi_addr_sz);
1138 _(OSCIOCIDENTIFY, WRITE, struct_oscsi_addr_sz);
1139 _(SCIOCDECONFIG, NONE, 0);
1140 _(SCIOCRECONFIG, NONE, 0);
1141 _(SCIOCRESET, NONE, 0);
1142 _(SCBUSIOSCAN, READ, struct_scbusioscan_args_sz);
1143 _(SCBUSIORESET, NONE, 0);
1144 _(SCBUSIODETACH, READ, struct_scbusiodetach_args_sz);
1145 _(SCBUSACCEL, READ, struct_scbusaccel_args_sz);
1146 /* Entries from file: sys/sockio.h */
1147 _(SIOCSHIWAT, READ, sizeof(int));
1148 _(SIOCGHIWAT, WRITE, sizeof(int));
1149 _(SIOCSLOWAT, READ, sizeof(int));
1150 _(SIOCGLOWAT, WRITE, sizeof(int));
1151 _(SIOCATMARK, WRITE, sizeof(int));
1152 _(SIOCSPGRP, READ, sizeof(int));
1153 _(SIOCGPGRP, WRITE, sizeof(int));
1154 _(SIOCPEELOFF, READWRITE, sizeof(int));
1155 _(SIOCADDRT, READ, struct_ortentry_sz);
1156 _(SIOCDELRT, READ, struct_ortentry_sz);
1157 _(SIOCSIFADDR, READ, struct_ifreq_sz);
1158 _(SIOCGIFADDR, READWRITE, struct_ifreq_sz);
1159 _(SIOCSIFDSTADDR, READ, struct_ifreq_sz);
1160 _(SIOCGIFDSTADDR, READWRITE, struct_ifreq_sz);
1161 _(SIOCSIFFLAGS, READ, struct_ifreq_sz);
1162 _(SIOCGIFFLAGS, READWRITE, struct_ifreq_sz);
1163 _(SIOCGIFBRDADDR, READWRITE, struct_ifreq_sz);
1164 _(SIOCSIFBRDADDR, READ, struct_ifreq_sz);
1165 _(SIOCGIFCONF, READWRITE, struct_ifconf_sz);
1166 _(SIOCGIFNETMASK, READWRITE, struct_ifreq_sz);
1167 _(SIOCSIFNETMASK, READ, struct_ifreq_sz);
1168 _(SIOCGIFMETRIC, READWRITE, struct_ifreq_sz);
1169 _(SIOCSIFMETRIC, READ, struct_ifreq_sz);
1170 _(SIOCDIFADDR, READ, struct_ifreq_sz);
1171 _(SIOCAIFADDR, READ, struct_ifaliasreq_sz);
1172 _(SIOCGIFALIAS, READWRITE, struct_ifaliasreq_sz);
1173 _(SIOCGIFAFLAG_IN, READWRITE, struct_ifreq_sz);
1174 _(SIOCALIFADDR, READ, struct_if_laddrreq_sz);
1175 _(SIOCGLIFADDR, READWRITE, struct_if_laddrreq_sz);
1176 _(SIOCDLIFADDR, READ, struct_if_laddrreq_sz);
1177 _(SIOCSIFADDRPREF, READ, struct_if_addrprefreq_sz);
1178 _(SIOCGIFADDRPREF, READWRITE, struct_if_addrprefreq_sz);
1179 _(SIOCADDMULTI, READ, struct_ifreq_sz);
1180 _(SIOCDELMULTI, READ, struct_ifreq_sz);
1181 _(SIOCGETVIFCNT, READWRITE, struct_sioc_vif_req_sz);
1182 _(SIOCGETSGCNT, READWRITE, struct_sioc_sg_req_sz);
1183 _(SIOCSIFMEDIA, READWRITE, struct_ifreq_sz);
1184 _(SIOCGIFMEDIA, READWRITE, struct_ifmediareq_sz);
1185 _(SIOCSIFGENERIC, READ, struct_ifreq_sz);
1186 _(SIOCGIFGENERIC, READWRITE, struct_ifreq_sz);
1187 _(SIOCSIFPHYADDR, READ, struct_ifaliasreq_sz);
1188 _(SIOCGIFPSRCADDR, READWRITE, struct_ifreq_sz);
1189 _(SIOCGIFPDSTADDR, READWRITE, struct_ifreq_sz);
1190 _(SIOCDIFPHYADDR, READ, struct_ifreq_sz);
1191 _(SIOCSLIFPHYADDR, READ, struct_if_laddrreq_sz);
1192 _(SIOCGLIFPHYADDR, READWRITE, struct_if_laddrreq_sz);
1193 _(SIOCSIFMTU, READ, struct_ifreq_sz);
1194 _(SIOCGIFMTU, READWRITE, struct_ifreq_sz);
1195 _(SIOCSDRVSPEC, READ, struct_ifdrv_sz);
1196 _(SIOCGDRVSPEC, READWRITE, struct_ifdrv_sz);
1197 _(SIOCIFCREATE, READ, struct_ifreq_sz);
1198 _(SIOCIFDESTROY, READ, struct_ifreq_sz);
1199 _(SIOCIFGCLONERS, READWRITE, struct_if_clonereq_sz);
1200 _(SIOCGIFDLT, READWRITE, struct_ifreq_sz);
1201 _(SIOCGIFCAP, READWRITE, struct_ifcapreq_sz);
1202 _(SIOCSIFCAP, READ, struct_ifcapreq_sz);
1203 _(SIOCSVH, READWRITE, struct_ifreq_sz);
1204 _(SIOCGVH, READWRITE, struct_ifreq_sz);
1205 _(SIOCINITIFADDR, READWRITE, struct_ifaddr_sz);
1206 _(SIOCGIFDATA, READWRITE, struct_ifdatareq_sz);
1207 _(SIOCZIFDATA, READWRITE, struct_ifdatareq_sz);
1208 _(SIOCGLINKSTR, READWRITE, struct_ifdrv_sz);
1209 _(SIOCSLINKSTR, READ, struct_ifdrv_sz);
1210 _(SIOCGETHERCAP, READWRITE, struct_eccapreq_sz);
1211 _(SIOCGIFINDEX, READWRITE, struct_ifreq_sz);
1212 _(SIOCSETHERCAP, READ, struct_eccapreq_sz);
1213 _(SIOCSIFDESCR, READ, struct_ifreq_sz);
1214 _(SIOCGIFDESCR, READWRITE, struct_ifreq_sz);
1215 _(SIOCGUMBINFO, READWRITE, struct_ifreq_sz);
1216 _(SIOCSUMBPARAM, READ, struct_ifreq_sz);
1217 _(SIOCGUMBPARAM, READWRITE, struct_ifreq_sz);
1218 _(SIOCSETPFSYNC, READ, struct_ifreq_sz);
1219 _(SIOCGETPFSYNC, READWRITE, struct_ifreq_sz);
1220 /* Entries from file: sys/timepps.h */
1221 _(PPS_IOC_CREATE, NONE, 0);
1222 _(PPS_IOC_DESTROY, NONE, 0);
1223 _(PPS_IOC_SETPARAMS, READ, struct_pps_params_sz);
1224 _(PPS_IOC_GETPARAMS, WRITE, struct_pps_params_sz);
1225 _(PPS_IOC_GETCAP, WRITE, sizeof(int));
1226 _(PPS_IOC_FETCH, READWRITE, struct_pps_info_sz);
1227 _(PPS_IOC_KCBIND, READ, sizeof(int));
1228 /* Entries from file: sys/ttycom.h */
1229 _(TIOCEXCL, NONE, 0);
1230 _(TIOCNXCL, NONE, 0);
1231 _(TIOCFLUSH, READ, sizeof(int));
1232 _(TIOCGETA, WRITE, struct_termios_sz);
1233 _(TIOCSETA, READ, struct_termios_sz);
1234 _(TIOCSETAW, READ, 0);
1235 _(TIOCSETAF, READ, 0);
1236 _(TIOCGETD, WRITE, sizeof(int));
1237 _(TIOCSETD, READ, sizeof(int));
1238 _(TIOCGLINED, WRITE, (32 * sizeof(char)));
1239 _(TIOCSLINED, READ, (32 * sizeof(char)));
1240 _(TIOCSBRK, NONE, 0);
1241 _(TIOCCBRK, NONE, 0);
1242 _(TIOCSDTR, NONE, 0);
1243 _(TIOCCDTR, NONE, 0);
1244 _(TIOCGPGRP, WRITE, sizeof(int));
1245 _(TIOCSPGRP, READ, sizeof(int));
1246 _(TIOCOUTQ, WRITE, sizeof(int));
1247 _(TIOCSTI, READ, sizeof(char));
1248 _(TIOCNOTTY, NONE, 0);
1249 _(TIOCPKT, READ, sizeof(int));
1250 _(TIOCSTOP, NONE, 0);
1251 _(TIOCSTART, NONE, 0);
1252 _(TIOCMSET, READ, sizeof(int));
1253 _(TIOCMBIS, READ, sizeof(int));
1254 _(TIOCMBIC, READ, sizeof(int));
1255 _(TIOCMGET, WRITE, sizeof(int));
1256 _(TIOCREMOTE, READ, sizeof(int));
1257 _(TIOCGWINSZ, WRITE, struct_winsize_sz);
1258 _(TIOCSWINSZ, READ, struct_winsize_sz);
1259 _(TIOCUCNTL, READ, sizeof(int));
1260 _(TIOCSTAT, READ, sizeof(int));
1261 _(TIOCGSID, WRITE, sizeof(int));
1262 _(TIOCCONS, READ, sizeof(int));
1263 _(TIOCSCTTY, NONE, 0);
1264 _(TIOCEXT, READ, sizeof(int));
1265 _(TIOCSIG, NONE, 0);
1266 _(TIOCDRAIN, NONE, 0);
1267 _(TIOCGFLAGS, WRITE, sizeof(int));
1268 _(TIOCSFLAGS, READ, sizeof(int));
1269 _(TIOCDCDTIMESTAMP, WRITE, struct_timeval_sz);
1270 _(TIOCRCVFRAME, READ, sizeof(uptr));
1271 _(TIOCXMTFRAME, READ, sizeof(uptr));
1272 _(TIOCPTMGET, WRITE, struct_ptmget_sz);
1273 _(TIOCGRANTPT, NONE, 0);
1274 _(TIOCPTSNAME, WRITE, struct_ptmget_sz);
1275 _(TIOCSQSIZE, READ, sizeof(int));
1276 _(TIOCGQSIZE, WRITE, sizeof(int));
1277 /* Entries from file: sys/verified_exec.h */
1278 _(VERIEXEC_LOAD, READ, struct_plistref_sz);
1279 _(VERIEXEC_TABLESIZE, READ, struct_plistref_sz);
1280 _(VERIEXEC_DELETE, READ, struct_plistref_sz);
1281 _(VERIEXEC_QUERY, READWRITE, struct_plistref_sz);
1282 _(VERIEXEC_DUMP, WRITE, struct_plistref_sz);
1283 _(VERIEXEC_FLUSH, NONE, 0);
1284 /* Entries from file: sys/videoio.h */
1285 _(VIDIOC_QUERYCAP, WRITE, struct_v4l2_capability_sz);
1286 _(VIDIOC_RESERVED, NONE, 0);
1287 _(VIDIOC_ENUM_FMT, READWRITE, struct_v4l2_fmtdesc_sz);
1288 _(VIDIOC_G_FMT, READWRITE, struct_v4l2_format_sz);
1289 _(VIDIOC_S_FMT, READWRITE, struct_v4l2_format_sz);
1290 _(VIDIOC_REQBUFS, READWRITE, struct_v4l2_requestbuffers_sz);
1291 _(VIDIOC_QUERYBUF, READWRITE, struct_v4l2_buffer_sz);
1292 _(VIDIOC_G_FBUF, WRITE, struct_v4l2_framebuffer_sz);
1293 _(VIDIOC_S_FBUF, READ, struct_v4l2_framebuffer_sz);
1294 _(VIDIOC_OVERLAY, READ, sizeof(int));
1295 _(VIDIOC_QBUF, READWRITE, struct_v4l2_buffer_sz);
1296 _(VIDIOC_DQBUF, READWRITE, struct_v4l2_buffer_sz);
1297 _(VIDIOC_STREAMON, READ, sizeof(int));
1298 _(VIDIOC_STREAMOFF, READ, sizeof(int));
1299 _(VIDIOC_G_PARM, READWRITE, struct_v4l2_streamparm_sz);
1300 _(VIDIOC_S_PARM, READWRITE, struct_v4l2_streamparm_sz);
1301 _(VIDIOC_G_STD, WRITE, sizeof(u64));
1302 _(VIDIOC_S_STD, READ, sizeof(u64));
1303 _(VIDIOC_ENUMSTD, READWRITE, struct_v4l2_standard_sz);
1304 _(VIDIOC_ENUMINPUT, READWRITE, struct_v4l2_input_sz);
1305 _(VIDIOC_G_CTRL, READWRITE, struct_v4l2_control_sz);
1306 _(VIDIOC_S_CTRL, READWRITE, struct_v4l2_control_sz);
1307 _(VIDIOC_G_TUNER, READWRITE, struct_v4l2_tuner_sz);
1308 _(VIDIOC_S_TUNER, READ, struct_v4l2_tuner_sz);
1309 _(VIDIOC_G_AUDIO, WRITE, struct_v4l2_audio_sz);
1310 _(VIDIOC_S_AUDIO, READ, struct_v4l2_audio_sz);
1311 _(VIDIOC_QUERYCTRL, READWRITE, struct_v4l2_queryctrl_sz);
1312 _(VIDIOC_QUERYMENU, READWRITE, struct_v4l2_querymenu_sz);
1313 _(VIDIOC_G_INPUT, WRITE, sizeof(int));
1314 _(VIDIOC_S_INPUT, READWRITE, sizeof(int));
1315 _(VIDIOC_G_OUTPUT, WRITE, sizeof(int));
1316 _(VIDIOC_S_OUTPUT, READWRITE, sizeof(int));
1317 _(VIDIOC_ENUMOUTPUT, READWRITE, struct_v4l2_output_sz);
1318 _(VIDIOC_G_AUDOUT, WRITE, struct_v4l2_audioout_sz);
1319 _(VIDIOC_S_AUDOUT, READ, struct_v4l2_audioout_sz);
1320 _(VIDIOC_G_MODULATOR, READWRITE, struct_v4l2_modulator_sz);
1321 _(VIDIOC_S_MODULATOR, READ, struct_v4l2_modulator_sz);
1322 _(VIDIOC_G_FREQUENCY, READWRITE, struct_v4l2_frequency_sz);
1323 _(VIDIOC_S_FREQUENCY, READ, struct_v4l2_frequency_sz);
1324 _(VIDIOC_CROPCAP, READWRITE, struct_v4l2_cropcap_sz);
1325 _(VIDIOC_G_CROP, READWRITE, struct_v4l2_crop_sz);
1326 _(VIDIOC_S_CROP, READ, struct_v4l2_crop_sz);
1327 _(VIDIOC_G_JPEGCOMP, WRITE, struct_v4l2_jpegcompression_sz);
1328 _(VIDIOC_S_JPEGCOMP, READ, struct_v4l2_jpegcompression_sz);
1329 _(VIDIOC_QUERYSTD, WRITE, sizeof(u64));
1330 _(VIDIOC_TRY_FMT, READWRITE, struct_v4l2_format_sz);
1331 _(VIDIOC_ENUMAUDIO, READWRITE, struct_v4l2_audio_sz);
1332 _(VIDIOC_ENUMAUDOUT, READWRITE, struct_v4l2_audioout_sz);
1333 _(VIDIOC_G_PRIORITY, WRITE, enum_v4l2_priority_sz);
1334 _(VIDIOC_S_PRIORITY, READ, enum_v4l2_priority_sz);
1335 _(VIDIOC_ENUM_FRAMESIZES, READWRITE, struct_v4l2_frmsizeenum_sz);
1336 _(VIDIOC_ENUM_FRAMEINTERVALS, READWRITE, struct_v4l2_frmivalenum_sz);
1337 /* Entries from file: sys/wdog.h */
1338 _(WDOGIOC_GMODE, READWRITE, struct_wdog_mode_sz);
1339 _(WDOGIOC_SMODE, READ, struct_wdog_mode_sz);
1340 _(WDOGIOC_WHICH, WRITE, struct_wdog_mode_sz);
1341 _(WDOGIOC_TICKLE, NONE, 0);
1342 _(WDOGIOC_GTICKLER, WRITE, sizeof(int));
1343 _(WDOGIOC_GWDOGS, READWRITE, struct_wdog_conf_sz);
1344 /* Entries from file: sys/kcov.h */
1345 _(KCOV_IOC_SETBUFSIZE, READ, sizeof(u64));
1346 _(KCOV_IOC_ENABLE, READ, sizeof(int));
1347 _(KCOV_IOC_DISABLE, NONE, 0);
1348 /* Entries from file: sys/ipmi.h */
1349 _(IPMICTL_RECEIVE_MSG_TRUNC, READWRITE, struct_ipmi_recv_sz);
1350 _(IPMICTL_RECEIVE_MSG, READWRITE, struct_ipmi_recv_sz);
1351 _(IPMICTL_SEND_COMMAND, READ, struct_ipmi_req_sz);
1352 _(IPMICTL_REGISTER_FOR_CMD, READ, struct_ipmi_cmdspec_sz);
1353 _(IPMICTL_UNREGISTER_FOR_CMD, READ, struct_ipmi_cmdspec_sz);
1354 _(IPMICTL_SET_GETS_EVENTS_CMD, READ, sizeof(int));
1355 _(IPMICTL_SET_MY_ADDRESS_CMD, READ, sizeof(unsigned int));
1356 _(IPMICTL_GET_MY_ADDRESS_CMD, WRITE, sizeof(unsigned int));
1357 _(IPMICTL_SET_MY_LUN_CMD, READ, sizeof(unsigned int));
1358 _(IPMICTL_GET_MY_LUN_CMD, WRITE, sizeof(unsigned int));
1359 /* Entries from file: soundcard.h */
1360 _(SNDCTL_DSP_RESET, NONE, 0);
1361 _(SNDCTL_DSP_SYNC, NONE, 0);
1362 _(SNDCTL_DSP_SPEED, READWRITE, sizeof(int));
1363 _(SOUND_PCM_READ_RATE, WRITE, sizeof(int));
1364 _(SNDCTL_DSP_STEREO, READWRITE, sizeof(int));
1365 _(SNDCTL_DSP_GETBLKSIZE, READWRITE, sizeof(int));
1366 _(SNDCTL_DSP_SETFMT, READWRITE, sizeof(int));
1367 _(SOUND_PCM_READ_BITS, WRITE, sizeof(int));
1368 _(SNDCTL_DSP_CHANNELS, READWRITE, sizeof(int));
1369 _(SOUND_PCM_READ_CHANNELS, WRITE, sizeof(int));
1370 _(SOUND_PCM_WRITE_FILTER, READWRITE, sizeof(int));
1371 _(SOUND_PCM_READ_FILTER, WRITE, sizeof(int));
1372 _(SNDCTL_DSP_POST, NONE, 0);
1373 _(SNDCTL_DSP_SUBDIVIDE, READWRITE, sizeof(int));
1374 _(SNDCTL_DSP_SETFRAGMENT, READWRITE, sizeof(int));
1375 _(SNDCTL_DSP_GETFMTS, WRITE, sizeof(int));
1376 _(SNDCTL_DSP_GETOSPACE, WRITE, struct_audio_buf_info_sz);
1377 _(SNDCTL_DSP_GETISPACE, WRITE, struct_audio_buf_info_sz);
1378 _(SNDCTL_DSP_NONBLOCK, NONE, 0);
1379 _(SNDCTL_DSP_GETCAPS, WRITE, sizeof(int));
1380 _(SNDCTL_DSP_GETTRIGGER, WRITE, sizeof(int));
1381 _(SNDCTL_DSP_SETTRIGGER, READ, sizeof(int));
1382 _(SNDCTL_DSP_GETIPTR, WRITE, struct_count_info_sz);
1383 _(SNDCTL_DSP_GETOPTR, WRITE, struct_count_info_sz);
1384 _(SNDCTL_DSP_MAPINBUF, WRITE, struct_buffmem_desc_sz);
1385 _(SNDCTL_DSP_MAPOUTBUF, WRITE, struct_buffmem_desc_sz);
1386 _(SNDCTL_DSP_SETSYNCRO, NONE, 0);
1387 _(SNDCTL_DSP_SETDUPLEX, NONE, 0);
1388 _(SNDCTL_DSP_PROFILE, READ, sizeof(int));
1389 _(SNDCTL_DSP_GETODELAY, WRITE, sizeof(int));
1390 _(SOUND_MIXER_INFO, WRITE, struct_mixer_info_sz);
1391 _(SOUND_OLD_MIXER_INFO, WRITE, struct__old_mixer_info_sz);
1392 _(OSS_GETVERSION, WRITE, sizeof(int));
1393 _(SNDCTL_SYSINFO, WRITE, struct_oss_sysinfo_sz);
1394 _(SNDCTL_AUDIOINFO, READWRITE, struct_oss_audioinfo_sz);
1395 _(SNDCTL_ENGINEINFO, READWRITE, struct_oss_audioinfo_sz);
1396 _(SNDCTL_DSP_GETPLAYVOL, WRITE, sizeof(unsigned int));
1397 _(SNDCTL_DSP_SETPLAYVOL, READ, sizeof(unsigned int));
1398 _(SNDCTL_DSP_GETRECVOL, WRITE, sizeof(unsigned int));
1399 _(SNDCTL_DSP_SETRECVOL, READ, sizeof(unsigned int));
1400 _(SNDCTL_DSP_SKIP, NONE, 0);
1401 _(SNDCTL_DSP_SILENCE, NONE, 0);
1402 /* Entries from file: dev/filemon/filemon.h (compat <= 9.99.26) */
1403 _(FILEMON_SET_FD, READWRITE, sizeof(int));
1404 _(FILEMON_SET_PID, READWRITE, sizeof(int));
1405 /* Entries from file: dev/usb/urio.h (compat <= 9.99.43) */
1406 _(URIO_SEND_COMMAND, READWRITE, struct_urio_command_sz);
1407 _(URIO_RECV_COMMAND, READWRITE, struct_urio_command_sz);
1408#undef _
1409} // NOLINT
1410
1411static bool ioctl_initialized = false;
1412
1413struct ioctl_desc_compare {
1414 bool operator()(const ioctl_desc &left, const ioctl_desc &right) const {
1415 return left.req < right.req;
1416 }
1417};
1418
1419static void ioctl_init() {
1420 ioctl_table_fill();
1421 Sort(ioctl_table, ioctl_table_size, ioctl_desc_compare());
1422
1423 bool bad = false;
1424 for (unsigned i = 0; i < ioctl_table_size - 1; ++i) {
1425 if (ioctl_table[i].req >= ioctl_table[i + 1].req) {
1426 Printf("Duplicate or unsorted ioctl request id %x >= %x (%s vs %s)\n",
1427 ioctl_table[i].req, ioctl_table[i + 1].req, ioctl_table[i].name,
1428 ioctl_table[i + 1].name);
1429 bad = true;
1430 }
1431 }
1432
1433 if (bad)
1434 Die();
1435
1436 ioctl_initialized = true;
1437}
1438
1439static const ioctl_desc *ioctl_table_lookup(unsigned req) {
1440 int left = 0;
1441 int right = ioctl_table_size;
1442 while (left < right) {
1443 int mid = (left + right) / 2;
1444 if (ioctl_table[mid].req < req)
1445 left = mid + 1;
1446 else
1447 right = mid;
1448 }
1449 if (left == right && ioctl_table[left].req == req)
1450 return ioctl_table + left;
1451 else
1452 return nullptr;
1453}
1454
1455static bool ioctl_decode(unsigned req, ioctl_desc *desc) {
1456 CHECK(desc);
1457 desc->req = req;
1458 desc->name = "<DECODED_IOCTL>";
1459 desc->size = IOC_SIZE(req);
1460 // Sanity check.
1461 if (desc->size > 0xFFFF)
1462 return false;
1463 unsigned dir = IOC_DIR(req);
1464 switch (dir) {
1465 case IOC_NONE:
1466 desc->type = ioctl_desc::NONE;
1467 break;
1468 case IOC_READ | IOC_WRITE:
1469 desc->type = ioctl_desc::READWRITE;
1470 break;
1471 case IOC_READ:
1472 desc->type = ioctl_desc::WRITE;
1473 break;
1474 case IOC_WRITE:
1475 desc->type = ioctl_desc::READ;
1476 break;
1477 default:
1478 return false;
1479 }
1480 // Size can be 0 iff type is NONE.
1481 if ((desc->type == IOC_NONE) != (desc->size == 0))
1482 return false;
1483 // Sanity check.
1484 if (IOC_TYPE(req) == 0)
1485 return false;
1486 return true;
1487}
1488
1489static const ioctl_desc *ioctl_lookup(unsigned req) {
1490 const ioctl_desc *desc = ioctl_table_lookup(req);
1491 if (desc)
1492 return desc;
1493
1494 // Try stripping access size from the request id.
1495 desc = ioctl_table_lookup(req & ~(IOC_SIZEMASK << IOC_SIZESHIFT));
1496 // Sanity check: requests that encode access size are either read or write and
1497 // have size of 0 in the table.
1498 if (desc && desc->size == 0 &&
1499 (desc->type == ioctl_desc::READWRITE || desc->type == ioctl_desc::WRITE ||
1500 desc->type == ioctl_desc::READ))
1501 return desc;
1502 return nullptr;
1503}
1504
1505static void ioctl_common_pre(void *ctx, const ioctl_desc *desc, int d,
1506 unsigned request, void *arg) {
1507 if (desc->type == ioctl_desc::READ || desc->type == ioctl_desc::READWRITE) {
1508 unsigned size = desc->size ? desc->size : IOC_SIZE(request);
1509 COMMON_INTERCEPTOR_READ_RANGE(ctx, arg, size);
1510 }
1511 if (desc->type != ioctl_desc::CUSTOM)
1512 return;
1513 if (request == IOCTL_SIOCGIFCONF) {
1514 struct __sanitizer_ifconf *ifc = (__sanitizer_ifconf *)arg;
1515 COMMON_INTERCEPTOR_READ_RANGE(ctx, (char *)&ifc->ifc_len,
1516 sizeof(ifc->ifc_len));
1517 }
1518}
1519
1520static void ioctl_common_post(void *ctx, const ioctl_desc *desc, int res, int d,
1521 unsigned request, void *arg) {
1522 if (desc->type == ioctl_desc::WRITE || desc->type == ioctl_desc::READWRITE) {
1523 // FIXME: add verbose output
1524 unsigned size = desc->size ? desc->size : IOC_SIZE(request);
1525 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, arg, size);
1526 }
1527 if (desc->type != ioctl_desc::CUSTOM)
1528 return;
1529 if (request == IOCTL_SIOCGIFCONF) {
1530 struct __sanitizer_ifconf *ifc = (__sanitizer_ifconf *)arg;
1531 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifc->ifc_ifcu.ifcu_req, ifc->ifc_len);
1532 }
1533}
1534
1535#endif // SANITIZER_NETBSD
lib/tsan/sanitizer_common/sanitizer_interface_internal.h created+118
...@@ -0,0 +1,118 @@
1//===-- sanitizer_interface_internal.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 run-time libraries of sanitizers.
10//
11// This header declares the sanitizer runtime interface functions.
12// The runtime library has to define these functions so the instrumented program
13// could call them.
14//
15// See also include/sanitizer/common_interface_defs.h
16//===----------------------------------------------------------------------===//
17#ifndef SANITIZER_INTERFACE_INTERNAL_H
18#define SANITIZER_INTERFACE_INTERNAL_H
19
20#include "sanitizer_internal_defs.h"
21
22extern "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
32 typedef struct {
33 int coverage_sandboxed;
34 __sanitizer::sptr coverage_fd;
35 unsigned int coverage_max_block_size;
36 } __sanitizer_sandbox_arguments;
37
38 // Notify the tools that the sandbox is going to be turned on.
39 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
40 __sanitizer_sandbox_on_notify(__sanitizer_sandbox_arguments *args);
41
42 // This function is called by the tool when it has just finished reporting
43 // an error. 'error_summary' is a one-line string that summarizes
44 // the error message. This function can be overridden by the client.
45 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
46 void __sanitizer_report_error_summary(const char *error_summary);
47
48 SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump();
49 SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_coverage(
50 const __sanitizer::uptr *pcs, const __sanitizer::uptr len);
51 SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_trace_pc_guard_coverage();
52
53 SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov(__sanitizer::u32 *guard);
54
55 // Returns 1 on the first call, then returns 0 thereafter. Called by the tool
56 // to ensure only one report is printed when multiple errors occur
57 // simultaneously.
58 SANITIZER_INTERFACE_ATTRIBUTE int __sanitizer_acquire_crash_state();
59
60 SANITIZER_INTERFACE_ATTRIBUTE
61 void __sanitizer_annotate_contiguous_container(const void *beg,
62 const void *end,
63 const void *old_mid,
64 const void *new_mid);
65 SANITIZER_INTERFACE_ATTRIBUTE
66 int __sanitizer_verify_contiguous_container(const void *beg, const void *mid,
67 const void *end);
68 SANITIZER_INTERFACE_ATTRIBUTE
69 const void *__sanitizer_contiguous_container_find_bad_address(
70 const void *beg, const void *mid, const void *end);
71
72 SANITIZER_INTERFACE_ATTRIBUTE
73 int __sanitizer_get_module_and_offset_for_pc(
74 __sanitizer::uptr pc, char *module_path,
75 __sanitizer::uptr module_path_len, __sanitizer::uptr *pc_offset);
76
77 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
78 void __sanitizer_cov_trace_cmp();
79 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
80 void __sanitizer_cov_trace_cmp1();
81 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
82 void __sanitizer_cov_trace_cmp2();
83 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
84 void __sanitizer_cov_trace_cmp4();
85 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
86 void __sanitizer_cov_trace_cmp8();
87 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
88 void __sanitizer_cov_trace_const_cmp1();
89 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
90 void __sanitizer_cov_trace_const_cmp2();
91 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
92 void __sanitizer_cov_trace_const_cmp4();
93 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
94 void __sanitizer_cov_trace_const_cmp8();
95 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
96 void __sanitizer_cov_trace_switch();
97 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
98 void __sanitizer_cov_trace_div4();
99 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
100 void __sanitizer_cov_trace_div8();
101 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
102 void __sanitizer_cov_trace_gep();
103 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
104 void __sanitizer_cov_trace_pc_indir();
105 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
106 void __sanitizer_cov_trace_pc_guard(__sanitizer::u32*);
107 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
108 void __sanitizer_cov_trace_pc_guard_init(__sanitizer::u32*,
109 __sanitizer::u32*);
110 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
111 void __sanitizer_cov_8bit_counters_init();
112 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
113 __sanitizer_cov_bool_flag_init();
114 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
115 __sanitizer_cov_pcs_init();
116} // extern "C"
117
118#endif // SANITIZER_INTERFACE_INTERNAL_H
lib/tsan/sanitizer_common/sanitizer_internal_defs.h created+459
...@@ -0,0 +1,459 @@
1//===-- sanitizer_internal_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 shared between AddressSanitizer and ThreadSanitizer.
10// It contains macro used in run-time libraries code.
11//===----------------------------------------------------------------------===//
12#ifndef SANITIZER_DEFS_H
13#define SANITIZER_DEFS_H
14
15#include "sanitizer_platform.h"
16
17#ifndef SANITIZER_DEBUG
18# define SANITIZER_DEBUG 0
19#endif
20
21#define SANITIZER_STRINGIFY_(S) #S
22#define SANITIZER_STRINGIFY(S) SANITIZER_STRINGIFY_(S)
23
24// Only use SANITIZER_*ATTRIBUTE* before the function return type!
25#if SANITIZER_WINDOWS
26#if SANITIZER_IMPORT_INTERFACE
27# define SANITIZER_INTERFACE_ATTRIBUTE __declspec(dllimport)
28#else
29# define SANITIZER_INTERFACE_ATTRIBUTE __declspec(dllexport)
30#endif
31# define SANITIZER_WEAK_ATTRIBUTE
32#elif SANITIZER_GO
33# define SANITIZER_INTERFACE_ATTRIBUTE
34# define SANITIZER_WEAK_ATTRIBUTE
35#else
36# define SANITIZER_INTERFACE_ATTRIBUTE __attribute__((visibility("default")))
37# define SANITIZER_WEAK_ATTRIBUTE __attribute__((weak))
38#endif
39
40// TLS is handled differently on different platforms
41#if SANITIZER_LINUX || SANITIZER_NETBSD || \
42 SANITIZER_FREEBSD || SANITIZER_OPENBSD
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
49//--------------------------- WEAK FUNCTIONS ---------------------------------//
50// When working with weak functions, to simplify the code and make it more
51// portable, when possible define a default implementation using this macro:
52//
53// SANITIZER_INTERFACE_WEAK_DEF(<return_type>, <name>, <parameter list>)
54//
55// For example:
56// SANITIZER_INTERFACE_WEAK_DEF(bool, compare, int a, int b) { return a > b; }
57//
58#if SANITIZER_WINDOWS
59#include "sanitizer_win_defs.h"
60# define SANITIZER_INTERFACE_WEAK_DEF(ReturnType, Name, ...) \
61 WIN_WEAK_EXPORT_DEF(ReturnType, Name, __VA_ARGS__)
62#else
63# define SANITIZER_INTERFACE_WEAK_DEF(ReturnType, Name, ...) \
64 extern "C" SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE \
65 ReturnType Name(__VA_ARGS__)
66#endif
67
68// SANITIZER_SUPPORTS_WEAK_HOOKS means that we support real weak functions that
69// will evaluate to a null pointer when not defined.
70#ifndef SANITIZER_SUPPORTS_WEAK_HOOKS
71#if (SANITIZER_LINUX || SANITIZER_SOLARIS) && !SANITIZER_GO
72# define SANITIZER_SUPPORTS_WEAK_HOOKS 1
73// Before Xcode 4.5, the Darwin linker doesn't reliably support undefined
74// weak symbols. Mac OS X 10.9/Darwin 13 is the first release only supported
75// by Xcode >= 4.5.
76#elif SANITIZER_MAC && \
77 __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1090 && !SANITIZER_GO
78# define SANITIZER_SUPPORTS_WEAK_HOOKS 1
79#else
80# define SANITIZER_SUPPORTS_WEAK_HOOKS 0
81#endif
82#endif // SANITIZER_SUPPORTS_WEAK_HOOKS
83// For some weak hooks that will be called very often and we want to avoid the
84// overhead of executing the default implementation when it is not necessary,
85// we can use the flag SANITIZER_SUPPORTS_WEAK_HOOKS to only define the default
86// implementation for platforms that doesn't support weak symbols. For example:
87//
88// #if !SANITIZER_SUPPORT_WEAK_HOOKS
89// SANITIZER_INTERFACE_WEAK_DEF(bool, compare_hook, int a, int b) {
90// return a > b;
91// }
92// #endif
93//
94// And then use it as: if (compare_hook) compare_hook(a, b);
95//----------------------------------------------------------------------------//
96
97
98// We can use .preinit_array section on Linux to call sanitizer initialization
99// functions very early in the process startup (unless PIC macro is defined).
100//
101// On FreeBSD, .preinit_array functions are called with rtld_bind_lock writer
102// lock held. It will lead to dead lock if unresolved PLT functions (which helds
103// rtld_bind_lock reader lock) are called inside .preinit_array functions.
104//
105// FIXME: do we have anything like this on Mac?
106#ifndef SANITIZER_CAN_USE_PREINIT_ARRAY
107#if ((SANITIZER_LINUX && !SANITIZER_ANDROID) || SANITIZER_OPENBSD || \
108 SANITIZER_FUCHSIA || SANITIZER_NETBSD) && !defined(PIC)
109#define SANITIZER_CAN_USE_PREINIT_ARRAY 1
110// Before Solaris 11.4, .preinit_array is fully supported only with GNU ld.
111// FIXME: Check for those conditions.
112#elif SANITIZER_SOLARIS && !defined(PIC)
113# define SANITIZER_CAN_USE_PREINIT_ARRAY 1
114#else
115# define SANITIZER_CAN_USE_PREINIT_ARRAY 0
116#endif
117#endif // SANITIZER_CAN_USE_PREINIT_ARRAY
118
119// GCC does not understand __has_feature
120#if !defined(__has_feature)
121# define __has_feature(x) 0
122#endif
123
124// Older GCCs do not understand __has_attribute.
125#if !defined(__has_attribute)
126# define __has_attribute(x) 0
127#endif
128
129// For portability reasons we do not include stddef.h, stdint.h or any other
130// system header, but we do need some basic types that are not defined
131// in a portable way by the language itself.
132namespace __sanitizer {
133
134#if defined(_WIN64)
135// 64-bit Windows uses LLP64 data model.
136typedef unsigned long long uptr;
137typedef signed long long sptr;
138#else
139typedef unsigned long uptr;
140typedef signed long sptr;
141#endif // defined(_WIN64)
142#if defined(__x86_64__)
143// Since x32 uses ILP32 data model in 64-bit hardware mode, we must use
144// 64-bit pointer to unwind stack frame.
145typedef unsigned long long uhwptr;
146#else
147typedef uptr uhwptr;
148#endif
149typedef unsigned char u8;
150typedef unsigned short u16;
151typedef unsigned int u32;
152typedef unsigned long long u64;
153typedef signed char s8;
154typedef signed short s16;
155typedef signed int s32;
156typedef signed long long s64;
157#if SANITIZER_WINDOWS
158// On Windows, files are HANDLE, which is a synonim of void*.
159// Use void* to avoid including <windows.h> everywhere.
160typedef void* fd_t;
161typedef unsigned error_t;
162#else
163typedef int fd_t;
164typedef int error_t;
165#endif
166#if SANITIZER_SOLARIS && !defined(_LP64)
167typedef long pid_t;
168#else
169typedef int pid_t;
170#endif
171
172#if SANITIZER_FREEBSD || SANITIZER_NETBSD || \
173 SANITIZER_OPENBSD || SANITIZER_MAC || \
174 (SANITIZER_SOLARIS && (defined(_LP64) || _FILE_OFFSET_BITS == 64)) || \
175 (SANITIZER_LINUX && defined(__x86_64__))
176typedef u64 OFF_T;
177#else
178typedef uptr OFF_T;
179#endif
180typedef u64 OFF64_T;
181
182#if (SANITIZER_WORDSIZE == 64) || SANITIZER_MAC
183typedef uptr operator_new_size_type;
184#else
185# if SANITIZER_OPENBSD || defined(__s390__) && !defined(__s390x__)
186// Special case: 31-bit s390 has unsigned long as size_t.
187typedef unsigned long operator_new_size_type;
188# else
189typedef u32 operator_new_size_type;
190# endif
191#endif
192
193typedef u64 tid_t;
194
195// ----------- ATTENTION -------------
196// This header should NOT include any other headers to avoid portability issues.
197
198// Common defs.
199#ifndef INLINE
200#define INLINE inline
201#endif
202#define INTERFACE_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
203#define SANITIZER_WEAK_DEFAULT_IMPL \
204 extern "C" SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE NOINLINE
205#define SANITIZER_WEAK_CXX_DEFAULT_IMPL \
206 extern "C++" SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE NOINLINE
207
208// Platform-specific defs.
209#if defined(_MSC_VER)
210# define ALWAYS_INLINE __forceinline
211// FIXME(timurrrr): do we need this on Windows?
212# define ALIAS(x)
213# define ALIGNED(x) __declspec(align(x))
214# define FORMAT(f, a)
215# define NOINLINE __declspec(noinline)
216# define NORETURN __declspec(noreturn)
217# define THREADLOCAL __declspec(thread)
218# define LIKELY(x) (x)
219# define UNLIKELY(x) (x)
220# define PREFETCH(x) /* _mm_prefetch(x, _MM_HINT_NTA) */ (void)0
221# define WARN_UNUSED_RESULT
222#else // _MSC_VER
223# define ALWAYS_INLINE inline __attribute__((always_inline))
224# define ALIAS(x) __attribute__((alias(x)))
225// Please only use the ALIGNED macro before the type.
226// Using ALIGNED after the variable declaration is not portable!
227# define ALIGNED(x) __attribute__((aligned(x)))
228# define FORMAT(f, a) __attribute__((format(printf, f, a)))
229# define NOINLINE __attribute__((noinline))
230# define NORETURN __attribute__((noreturn))
231# define THREADLOCAL __thread
232# define LIKELY(x) __builtin_expect(!!(x), 1)
233# define UNLIKELY(x) __builtin_expect(!!(x), 0)
234# if defined(__i386__) || defined(__x86_64__)
235// __builtin_prefetch(x) generates prefetchnt0 on x86
236# define PREFETCH(x) __asm__("prefetchnta (%0)" : : "r" (x))
237# else
238# define PREFETCH(x) __builtin_prefetch(x)
239# endif
240# define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
241#endif // _MSC_VER
242
243#if !defined(_MSC_VER) || defined(__clang__)
244# define UNUSED __attribute__((unused))
245# define USED __attribute__((used))
246#else
247# define UNUSED
248# define USED
249#endif
250
251#if !defined(_MSC_VER) || defined(__clang__) || MSC_PREREQ(1900)
252# define NOEXCEPT noexcept
253#else
254# define NOEXCEPT throw()
255#endif
256
257// Unaligned versions of basic types.
258typedef ALIGNED(1) u16 uu16;
259typedef ALIGNED(1) u32 uu32;
260typedef ALIGNED(1) u64 uu64;
261typedef ALIGNED(1) s16 us16;
262typedef ALIGNED(1) s32 us32;
263typedef ALIGNED(1) s64 us64;
264
265#if SANITIZER_WINDOWS
266} // namespace __sanitizer
267typedef unsigned long DWORD;
268namespace __sanitizer {
269typedef DWORD thread_return_t;
270# define THREAD_CALLING_CONV __stdcall
271#else // _WIN32
272typedef void* thread_return_t;
273# define THREAD_CALLING_CONV
274#endif // _WIN32
275typedef thread_return_t (THREAD_CALLING_CONV *thread_callback_t)(void* arg);
276
277// NOTE: Functions below must be defined in each run-time.
278void NORETURN Die();
279
280void NORETURN CheckFailed(const char *file, int line, const char *cond,
281 u64 v1, u64 v2);
282
283// Check macro
284#define RAW_CHECK_MSG(expr, msg) do { \
285 if (UNLIKELY(!(expr))) { \
286 RawWrite(msg); \
287 Die(); \
288 } \
289} while (0)
290
291#define RAW_CHECK(expr) RAW_CHECK_MSG(expr, #expr)
292
293#define CHECK_IMPL(c1, op, c2) \
294 do { \
295 __sanitizer::u64 v1 = (__sanitizer::u64)(c1); \
296 __sanitizer::u64 v2 = (__sanitizer::u64)(c2); \
297 if (UNLIKELY(!(v1 op v2))) \
298 __sanitizer::CheckFailed(__FILE__, __LINE__, \
299 "(" #c1 ") " #op " (" #c2 ")", v1, v2); \
300 } while (false) \
301/**/
302
303#define CHECK(a) CHECK_IMPL((a), !=, 0)
304#define CHECK_EQ(a, b) CHECK_IMPL((a), ==, (b))
305#define CHECK_NE(a, b) CHECK_IMPL((a), !=, (b))
306#define CHECK_LT(a, b) CHECK_IMPL((a), <, (b))
307#define CHECK_LE(a, b) CHECK_IMPL((a), <=, (b))
308#define CHECK_GT(a, b) CHECK_IMPL((a), >, (b))
309#define CHECK_GE(a, b) CHECK_IMPL((a), >=, (b))
310
311#if SANITIZER_DEBUG
312#define DCHECK(a) CHECK(a)
313#define DCHECK_EQ(a, b) CHECK_EQ(a, b)
314#define DCHECK_NE(a, b) CHECK_NE(a, b)
315#define DCHECK_LT(a, b) CHECK_LT(a, b)
316#define DCHECK_LE(a, b) CHECK_LE(a, b)
317#define DCHECK_GT(a, b) CHECK_GT(a, b)
318#define DCHECK_GE(a, b) CHECK_GE(a, b)
319#else
320#define DCHECK(a)
321#define DCHECK_EQ(a, b)
322#define DCHECK_NE(a, b)
323#define DCHECK_LT(a, b)
324#define DCHECK_LE(a, b)
325#define DCHECK_GT(a, b)
326#define DCHECK_GE(a, b)
327#endif
328
329#define UNREACHABLE(msg) do { \
330 CHECK(0 && msg); \
331 Die(); \
332} while (0)
333
334#define UNIMPLEMENTED() UNREACHABLE("unimplemented")
335
336#define COMPILER_CHECK(pred) IMPL_COMPILER_ASSERT(pred, __LINE__)
337
338#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
339
340#define IMPL_PASTE(a, b) a##b
341#define IMPL_COMPILER_ASSERT(pred, line) \
342 typedef char IMPL_PASTE(assertion_failed_##_, line)[2*(int)(pred)-1]
343
344// Limits for integral types. We have to redefine it in case we don't
345// have stdint.h (like in Visual Studio 9).
346#undef __INT64_C
347#undef __UINT64_C
348#if SANITIZER_WORDSIZE == 64
349# define __INT64_C(c) c ## L
350# define __UINT64_C(c) c ## UL
351#else
352# define __INT64_C(c) c ## LL
353# define __UINT64_C(c) c ## ULL
354#endif // SANITIZER_WORDSIZE == 64
355#undef INT32_MIN
356#define INT32_MIN (-2147483647-1)
357#undef INT32_MAX
358#define INT32_MAX (2147483647)
359#undef UINT32_MAX
360#define UINT32_MAX (4294967295U)
361#undef INT64_MIN
362#define INT64_MIN (-__INT64_C(9223372036854775807)-1)
363#undef INT64_MAX
364#define INT64_MAX (__INT64_C(9223372036854775807))
365#undef UINT64_MAX
366#define UINT64_MAX (__UINT64_C(18446744073709551615))
367#undef UINTPTR_MAX
368#if SANITIZER_WORDSIZE == 64
369# define UINTPTR_MAX (18446744073709551615UL)
370#else
371# define UINTPTR_MAX (4294967295U)
372#endif // SANITIZER_WORDSIZE == 64
373
374enum LinkerInitialized { LINKER_INITIALIZED = 0 };
375
376#if !defined(_MSC_VER) || defined(__clang__)
377#if SANITIZER_S390_31
378#define GET_CALLER_PC() \
379 (__sanitizer::uptr) __builtin_extract_return_addr(__builtin_return_address(0))
380#else
381#define GET_CALLER_PC() (__sanitizer::uptr) __builtin_return_address(0)
382#endif
383#define GET_CURRENT_FRAME() (__sanitizer::uptr) __builtin_frame_address(0)
384inline void Trap() {
385 __builtin_trap();
386}
387#else
388extern "C" void* _ReturnAddress(void);
389extern "C" void* _AddressOfReturnAddress(void);
390# pragma intrinsic(_ReturnAddress)
391# pragma intrinsic(_AddressOfReturnAddress)
392#define GET_CALLER_PC() (__sanitizer::uptr) _ReturnAddress()
393// CaptureStackBackTrace doesn't need to know BP on Windows.
394#define GET_CURRENT_FRAME() \
395 (((__sanitizer::uptr)_AddressOfReturnAddress()) + sizeof(__sanitizer::uptr))
396
397extern "C" void __ud2(void);
398# pragma intrinsic(__ud2)
399inline void Trap() {
400 __ud2();
401}
402#endif
403
404#define HANDLE_EINTR(res, f) \
405 { \
406 int rverrno; \
407 do { \
408 res = (f); \
409 } while (internal_iserror(res, &rverrno) && rverrno == EINTR); \
410 }
411
412// Forces the compiler to generate a frame pointer in the function.
413#define ENABLE_FRAME_POINTER \
414 do { \
415 volatile __sanitizer::uptr enable_fp; \
416 enable_fp = GET_CURRENT_FRAME(); \
417 (void)enable_fp; \
418 } while (0)
419
420} // namespace __sanitizer
421
422namespace __asan {
423using namespace __sanitizer;
424}
425namespace __dsan {
426using namespace __sanitizer;
427}
428namespace __dfsan {
429using namespace __sanitizer;
430}
431namespace __lsan {
432using namespace __sanitizer;
433}
434namespace __msan {
435using namespace __sanitizer;
436}
437namespace __hwasan {
438using namespace __sanitizer;
439}
440namespace __tsan {
441using namespace __sanitizer;
442}
443namespace __scudo {
444using namespace __sanitizer;
445}
446namespace __ubsan {
447using namespace __sanitizer;
448}
449namespace __xray {
450using namespace __sanitizer;
451}
452namespace __interception {
453using namespace __sanitizer;
454}
455namespace __hwasan {
456using namespace __sanitizer;
457}
458
459#endif // SANITIZER_DEFS_H
lib/tsan/sanitizer_common/sanitizer_lfstack.h created+72
...@@ -0,0 +1,72 @@
1//===-- sanitizer_lfstack.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// Lock-free stack.
10// Uses 32/17 bits as ABA-counter on 32/64-bit platforms.
11// The memory passed to Push() must not be ever munmap'ed.
12// The type T must contain T *next field.
13//
14//===----------------------------------------------------------------------===//
15
16#ifndef SANITIZER_LFSTACK_H
17#define SANITIZER_LFSTACK_H
18
19#include "sanitizer_internal_defs.h"
20#include "sanitizer_common.h"
21#include "sanitizer_atomic.h"
22
23namespace __sanitizer {
24
25template<typename T>
26struct LFStack {
27 void Clear() {
28 atomic_store(&head_, 0, memory_order_relaxed);
29 }
30
31 bool Empty() const {
32 return (atomic_load(&head_, memory_order_relaxed) & kPtrMask) == 0;
33 }
34
35 void Push(T *p) {
36 u64 cmp = atomic_load(&head_, memory_order_relaxed);
37 for (;;) {
38 u64 cnt = (cmp & kCounterMask) + kCounterInc;
39 u64 xch = (u64)(uptr)p | cnt;
40 p->next = (T*)(uptr)(cmp & kPtrMask);
41 if (atomic_compare_exchange_weak(&head_, &cmp, xch,
42 memory_order_release))
43 break;
44 }
45 }
46
47 T *Pop() {
48 u64 cmp = atomic_load(&head_, memory_order_acquire);
49 for (;;) {
50 T *cur = (T*)(uptr)(cmp & kPtrMask);
51 if (!cur)
52 return nullptr;
53 T *nxt = cur->next;
54 u64 cnt = (cmp & kCounterMask);
55 u64 xch = (u64)(uptr)nxt | cnt;
56 if (atomic_compare_exchange_weak(&head_, &cmp, xch,
57 memory_order_acquire))
58 return cur;
59 }
60 }
61
62 // private:
63 static const int kCounterBits = FIRST_32_SECOND_64(32, 17);
64 static const u64 kPtrMask = ((u64)-1) >> kCounterBits;
65 static const u64 kCounterMask = ~kPtrMask;
66 static const u64 kCounterInc = kPtrMask + 1;
67
68 atomic_uint64_t head_;
69};
70} // namespace __sanitizer
71
72#endif // SANITIZER_LFSTACK_H
lib/tsan/sanitizer_common/sanitizer_libc.cpp created+280
...@@ -0,0 +1,280 @@
1//===-- sanitizer_libc.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 shared between AddressSanitizer and ThreadSanitizer
10// run-time libraries. See sanitizer_libc.h for details.
11//===----------------------------------------------------------------------===//
12
13#include "sanitizer_allocator_internal.h"
14#include "sanitizer_common.h"
15#include "sanitizer_libc.h"
16
17namespace __sanitizer {
18
19s64 internal_atoll(const char *nptr) {
20 return internal_simple_strtoll(nptr, nullptr, 10);
21}
22
23void *internal_memchr(const void *s, int c, uptr n) {
24 const char *t = (const char *)s;
25 for (uptr i = 0; i < n; ++i, ++t)
26 if (*t == c)
27 return reinterpret_cast<void *>(const_cast<char *>(t));
28 return nullptr;
29}
30
31void *internal_memrchr(const void *s, int c, uptr n) {
32 const char *t = (const char *)s;
33 void *res = nullptr;
34 for (uptr i = 0; i < n; ++i, ++t) {
35 if (*t == c) res = reinterpret_cast<void *>(const_cast<char *>(t));
36 }
37 return res;
38}
39
40int internal_memcmp(const void* s1, const void* s2, uptr n) {
41 const char *t1 = (const char *)s1;
42 const char *t2 = (const char *)s2;
43 for (uptr i = 0; i < n; ++i, ++t1, ++t2)
44 if (*t1 != *t2)
45 return *t1 < *t2 ? -1 : 1;
46 return 0;
47}
48
49void *internal_memcpy(void *dest, const void *src, uptr n) {
50 char *d = (char*)dest;
51 const char *s = (const char *)src;
52 for (uptr i = 0; i < n; ++i)
53 d[i] = s[i];
54 return dest;
55}
56
57void *internal_memmove(void *dest, const void *src, uptr n) {
58 char *d = (char*)dest;
59 const char *s = (const char *)src;
60 sptr i, signed_n = (sptr)n;
61 CHECK_GE(signed_n, 0);
62 if (d < s) {
63 for (i = 0; i < signed_n; ++i)
64 d[i] = s[i];
65 } else {
66 if (d > s && signed_n > 0) {
67 for (i = signed_n - 1; i >= 0; --i) {
68 d[i] = s[i];
69 }
70 }
71 }
72 return dest;
73}
74
75void *internal_memset(void* s, int c, uptr n) {
76 // Optimize for the most performance-critical case:
77 if ((reinterpret_cast<uptr>(s) % 16) == 0 && (n % 16) == 0) {
78 u64 *p = reinterpret_cast<u64*>(s);
79 u64 *e = p + n / 8;
80 u64 v = c;
81 v |= v << 8;
82 v |= v << 16;
83 v |= v << 32;
84 for (; p < e; p += 2)
85 p[0] = p[1] = v;
86 return s;
87 }
88 // The next line prevents Clang from making a call to memset() instead of the
89 // loop below.
90 // FIXME: building the runtime with -ffreestanding is a better idea. However
91 // there currently are linktime problems due to PR12396.
92 char volatile *t = (char*)s;
93 for (uptr i = 0; i < n; ++i, ++t) {
94 *t = c;
95 }
96 return s;
97}
98
99uptr internal_strcspn(const char *s, const char *reject) {
100 uptr i;
101 for (i = 0; s[i]; i++) {
102 if (internal_strchr(reject, s[i]))
103 return i;
104 }
105 return i;
106}
107
108char* internal_strdup(const char *s) {
109 uptr len = internal_strlen(s);
110 char *s2 = (char*)InternalAlloc(len + 1);
111 internal_memcpy(s2, s, len);
112 s2[len] = 0;
113 return s2;
114}
115
116int internal_strcmp(const char *s1, const char *s2) {
117 while (true) {
118 unsigned c1 = *s1;
119 unsigned c2 = *s2;
120 if (c1 != c2) return (c1 < c2) ? -1 : 1;
121 if (c1 == 0) break;
122 s1++;
123 s2++;
124 }
125 return 0;
126}
127
128int internal_strncmp(const char *s1, const char *s2, uptr n) {
129 for (uptr i = 0; i < n; i++) {
130 unsigned c1 = *s1;
131 unsigned c2 = *s2;
132 if (c1 != c2) return (c1 < c2) ? -1 : 1;
133 if (c1 == 0) break;
134 s1++;
135 s2++;
136 }
137 return 0;
138}
139
140char* internal_strchr(const char *s, int c) {
141 while (true) {
142 if (*s == (char)c)
143 return const_cast<char *>(s);
144 if (*s == 0)
145 return nullptr;
146 s++;
147 }
148}
149
150char *internal_strchrnul(const char *s, int c) {
151 char *res = internal_strchr(s, c);
152 if (!res)
153 res = const_cast<char *>(s) + internal_strlen(s);
154 return res;
155}
156
157char *internal_strrchr(const char *s, int c) {
158 const char *res = nullptr;
159 for (uptr i = 0; s[i]; i++) {
160 if (s[i] == c) res = s + i;
161 }
162 return const_cast<char *>(res);
163}
164
165uptr internal_strlen(const char *s) {
166 uptr i = 0;
167 while (s[i]) i++;
168 return i;
169}
170
171uptr internal_strlcat(char *dst, const char *src, uptr maxlen) {
172 const uptr srclen = internal_strlen(src);
173 const uptr dstlen = internal_strnlen(dst, maxlen);
174 if (dstlen == maxlen) return maxlen + srclen;
175 if (srclen < maxlen - dstlen) {
176 internal_memmove(dst + dstlen, src, srclen + 1);
177 } else {
178 internal_memmove(dst + dstlen, src, maxlen - dstlen - 1);
179 dst[maxlen - 1] = '\0';
180 }
181 return dstlen + srclen;
182}
183
184char *internal_strncat(char *dst, const char *src, uptr n) {
185 uptr len = internal_strlen(dst);
186 uptr i;
187 for (i = 0; i < n && src[i]; i++)
188 dst[len + i] = src[i];
189 dst[len + i] = 0;
190 return dst;
191}
192
193uptr internal_strlcpy(char *dst, const char *src, uptr maxlen) {
194 const uptr srclen = internal_strlen(src);
195 if (srclen < maxlen) {
196 internal_memmove(dst, src, srclen + 1);
197 } else if (maxlen != 0) {
198 internal_memmove(dst, src, maxlen - 1);
199 dst[maxlen - 1] = '\0';
200 }
201 return srclen;
202}
203
204char *internal_strncpy(char *dst, const char *src, uptr n) {
205 uptr i;
206 for (i = 0; i < n && src[i]; i++)
207 dst[i] = src[i];
208 internal_memset(dst + i, '\0', n - i);
209 return dst;
210}
211
212uptr internal_strnlen(const char *s, uptr maxlen) {
213 uptr i = 0;
214 while (i < maxlen && s[i]) i++;
215 return i;
216}
217
218char *internal_strstr(const char *haystack, const char *needle) {
219 // This is O(N^2), but we are not using it in hot places.
220 uptr len1 = internal_strlen(haystack);
221 uptr len2 = internal_strlen(needle);
222 if (len1 < len2) return nullptr;
223 for (uptr pos = 0; pos <= len1 - len2; pos++) {
224 if (internal_memcmp(haystack + pos, needle, len2) == 0)
225 return const_cast<char *>(haystack) + pos;
226 }
227 return nullptr;
228}
229
230s64 internal_simple_strtoll(const char *nptr, const char **endptr, int base) {
231 CHECK_EQ(base, 10);
232 while (IsSpace(*nptr)) nptr++;
233 int sgn = 1;
234 u64 res = 0;
235 bool have_digits = false;
236 char *old_nptr = const_cast<char *>(nptr);
237 if (*nptr == '+') {
238 sgn = 1;
239 nptr++;
240 } else if (*nptr == '-') {
241 sgn = -1;
242 nptr++;
243 }
244 while (IsDigit(*nptr)) {
245 res = (res <= UINT64_MAX / 10) ? res * 10 : UINT64_MAX;
246 int digit = ((*nptr) - '0');
247 res = (res <= UINT64_MAX - digit) ? res + digit : UINT64_MAX;
248 have_digits = true;
249 nptr++;
250 }
251 if (endptr) {
252 *endptr = (have_digits) ? const_cast<char *>(nptr) : old_nptr;
253 }
254 if (sgn > 0) {
255 return (s64)(Min((u64)INT64_MAX, res));
256 } else {
257 return (res > INT64_MAX) ? INT64_MIN : ((s64)res * -1);
258 }
259}
260
261bool mem_is_zero(const char *beg, uptr size) {
262 CHECK_LE(size, 1ULL << FIRST_32_SECOND_64(30, 40)); // Sanity check.
263 const char *end = beg + size;
264 uptr *aligned_beg = (uptr *)RoundUpTo((uptr)beg, sizeof(uptr));
265 uptr *aligned_end = (uptr *)RoundDownTo((uptr)end, sizeof(uptr));
266 uptr all = 0;
267 // Prologue.
268 for (const char *mem = beg; mem < (char*)aligned_beg && mem < end; mem++)
269 all |= *mem;
270 // Aligned loop.
271 for (; aligned_beg < aligned_end; aligned_beg++)
272 all |= *aligned_beg;
273 // Epilogue.
274 if ((char *)aligned_end >= beg) {
275 for (const char *mem = (char *)aligned_end; mem < end; mem++) all |= *mem;
276 }
277 return all == 0;
278}
279
280} // namespace __sanitizer
lib/tsan/sanitizer_common/sanitizer_libc.h created+85
...@@ -0,0 +1,85 @@
1//===-- sanitizer_libc.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 AddressSanitizer and ThreadSanitizer
10// run-time libraries.
11// These tools can not use some of the libc functions directly because those
12// functions are intercepted. Instead, we implement a tiny subset of libc here.
13// FIXME: Some of functions declared in this file are in fact POSIX, not libc.
14//===----------------------------------------------------------------------===//
15
16#ifndef SANITIZER_LIBC_H
17#define SANITIZER_LIBC_H
18
19// ----------- ATTENTION -------------
20// This header should NOT include any other headers from sanitizer runtime.
21#include "sanitizer_internal_defs.h"
22
23namespace __sanitizer {
24
25// internal_X() is a custom implementation of X() for use in RTL.
26
27// String functions
28s64 internal_atoll(const char *nptr);
29void *internal_memchr(const void *s, int c, uptr n);
30void *internal_memrchr(const void *s, int c, uptr n);
31int 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);
34// Should not be used in performance-critical places.
35void *internal_memset(void *s, int c, uptr n);
36char* internal_strchr(const char *s, int c);
37char *internal_strchrnul(const char *s, int c);
38int internal_strcmp(const char *s1, const char *s2);
39uptr internal_strcspn(const char *s, const char *reject);
40char *internal_strdup(const char *s);
41uptr internal_strlen(const char *s);
42uptr internal_strlcat(char *dst, const char *src, uptr maxlen);
43char *internal_strncat(char *dst, const char *src, uptr n);
44int internal_strncmp(const char *s1, const char *s2, uptr n);
45uptr internal_strlcpy(char *dst, const char *src, uptr maxlen);
46char *internal_strncpy(char *dst, const char *src, uptr n);
47uptr internal_strnlen(const char *s, uptr maxlen);
48char *internal_strrchr(const char *s, int c);
49char *internal_strstr(const char *haystack, const char *needle);
50// Works only for base=10 and doesn't set errno.
51s64 internal_simple_strtoll(const char *nptr, const char **endptr, int base);
52int internal_snprintf(char *buffer, uptr length, const char *format, ...);
53
54// Return true if all bytes in [mem, mem+size) are zero.
55// Optimized for the case when the result is true.
56bool mem_is_zero(const char *mem, uptr size);
57
58// I/O
59// Define these as macros so we can use them in linker initialized global
60// structs without dynamic initialization.
61#define kInvalidFd ((fd_t)-1)
62#define kStdinFd ((fd_t)0)
63#define kStdoutFd ((fd_t)1)
64#define kStderrFd ((fd_t)2)
65
66uptr internal_ftruncate(fd_t fd, uptr size);
67
68// OS
69void NORETURN internal__exit(int exitcode);
70unsigned int internal_sleep(unsigned int seconds);
71
72uptr internal_getpid();
73uptr internal_getppid();
74
75int internal_dlinfo(void *handle, int request, void *p);
76
77// Threading
78uptr internal_sched_yield();
79
80// Error handling
81bool internal_iserror(uptr retval, int *rverrno = nullptr);
82
83} // namespace __sanitizer
84
85#endif // SANITIZER_LIBC_H
lib/tsan/sanitizer_common/sanitizer_libignore.cpp created+129
...@@ -0,0 +1,129 @@
1//===-- sanitizer_libignore.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_platform.h"
10
11#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_MAC || \
12 SANITIZER_NETBSD || SANITIZER_OPENBSD
13
14#include "sanitizer_libignore.h"
15#include "sanitizer_flags.h"
16#include "sanitizer_posix.h"
17#include "sanitizer_procmaps.h"
18
19namespace __sanitizer {
20
21LibIgnore::LibIgnore(LinkerInitialized) {
22}
23
24void LibIgnore::AddIgnoredLibrary(const char *name_templ) {
25 BlockingMutexLock lock(&mutex_);
26 if (count_ >= kMaxLibs) {
27 Report("%s: too many ignored libraries (max: %d)\n", SanitizerToolName,
28 kMaxLibs);
29 Die();
30 }
31 Lib *lib = &libs_[count_++];
32 lib->templ = internal_strdup(name_templ);
33 lib->name = nullptr;
34 lib->real_name = nullptr;
35 lib->loaded = false;
36}
37
38void LibIgnore::OnLibraryLoaded(const char *name) {
39 BlockingMutexLock lock(&mutex_);
40 // Try to match suppressions with symlink target.
41 InternalScopedString buf(kMaxPathLength);
42 if (name && internal_readlink(name, buf.data(), buf.size() - 1) > 0 &&
43 buf[0]) {
44 for (uptr i = 0; i < count_; i++) {
45 Lib *lib = &libs_[i];
46 if (!lib->loaded && (!lib->real_name) &&
47 TemplateMatch(lib->templ, name))
48 lib->real_name = internal_strdup(buf.data());
49 }
50 }
51
52 // Scan suppressions list and find newly loaded and unloaded libraries.
53 ListOfModules modules;
54 modules.init();
55 for (uptr i = 0; i < count_; i++) {
56 Lib *lib = &libs_[i];
57 bool loaded = false;
58 for (const auto &mod : modules) {
59 for (const auto &range : mod.ranges()) {
60 if (!range.executable)
61 continue;
62 if (!TemplateMatch(lib->templ, mod.full_name()) &&
63 !(lib->real_name &&
64 internal_strcmp(lib->real_name, mod.full_name()) == 0))
65 continue;
66 if (loaded) {
67 Report("%s: called_from_lib suppression '%s' is matched against"
68 " 2 libraries: '%s' and '%s'\n",
69 SanitizerToolName, lib->templ, lib->name, mod.full_name());
70 Die();
71 }
72 loaded = true;
73 if (lib->loaded)
74 continue;
75 VReport(1,
76 "Matched called_from_lib suppression '%s' against library"
77 " '%s'\n",
78 lib->templ, mod.full_name());
79 lib->loaded = true;
80 lib->name = internal_strdup(mod.full_name());
81 const uptr idx =
82 atomic_load(&ignored_ranges_count_, memory_order_relaxed);
83 CHECK_LT(idx, ARRAY_SIZE(ignored_code_ranges_));
84 ignored_code_ranges_[idx].begin = range.beg;
85 ignored_code_ranges_[idx].end = range.end;
86 atomic_store(&ignored_ranges_count_, idx + 1, memory_order_release);
87 break;
88 }
89 }
90 if (lib->loaded && !loaded) {
91 Report("%s: library '%s' that was matched against called_from_lib"
92 " suppression '%s' is unloaded\n",
93 SanitizerToolName, lib->name, lib->templ);
94 Die();
95 }
96 }
97
98 // Track instrumented ranges.
99 if (track_instrumented_libs_) {
100 for (const auto &mod : modules) {
101 if (!mod.instrumented())
102 continue;
103 for (const auto &range : mod.ranges()) {
104 if (!range.executable)
105 continue;
106 if (IsPcInstrumented(range.beg) && IsPcInstrumented(range.end - 1))
107 continue;
108 VReport(1, "Adding instrumented range %p-%p from library '%s'\n",
109 range.beg, range.end, mod.full_name());
110 const uptr idx =
111 atomic_load(&instrumented_ranges_count_, memory_order_relaxed);
112 CHECK_LT(idx, ARRAY_SIZE(instrumented_code_ranges_));
113 instrumented_code_ranges_[idx].begin = range.beg;
114 instrumented_code_ranges_[idx].end = range.end;
115 atomic_store(&instrumented_ranges_count_, idx + 1,
116 memory_order_release);
117 }
118 }
119 }
120}
121
122void LibIgnore::OnLibraryUnloaded() {
123 OnLibraryLoaded(nullptr);
124}
125
126} // namespace __sanitizer
127
128#endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_MAC ||
129 // SANITIZER_NETBSD
lib/tsan/sanitizer_common/sanitizer_libignore.h created+115
...@@ -0,0 +1,115 @@
1//===-- sanitizer_libignore.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// LibIgnore allows to ignore all interceptors called from a particular set
10// of dynamic libraries. LibIgnore can be initialized with several templates
11// of names of libraries to be ignored. It finds code ranges for the libraries;
12// and checks whether the provided PC value belongs to the code ranges.
13//
14//===----------------------------------------------------------------------===//
15
16#ifndef SANITIZER_LIBIGNORE_H
17#define SANITIZER_LIBIGNORE_H
18
19#include "sanitizer_internal_defs.h"
20#include "sanitizer_common.h"
21#include "sanitizer_atomic.h"
22#include "sanitizer_mutex.h"
23
24namespace __sanitizer {
25
26class LibIgnore {
27 public:
28 explicit LibIgnore(LinkerInitialized);
29
30 // Must be called during initialization.
31 void AddIgnoredLibrary(const char *name_templ);
32 void IgnoreNoninstrumentedModules(bool enable) {
33 track_instrumented_libs_ = enable;
34 }
35
36 // Must be called after a new dynamic library is loaded.
37 void OnLibraryLoaded(const char *name);
38
39 // Must be called after a dynamic library is unloaded.
40 void OnLibraryUnloaded();
41
42 // Checks whether the provided PC belongs to one of the ignored libraries or
43 // the PC should be ignored because it belongs to an non-instrumented module
44 // (when ignore_noninstrumented_modules=1). Also returns true via
45 // "pc_in_ignored_lib" if the PC is in an ignored library, false otherwise.
46 bool IsIgnored(uptr pc, bool *pc_in_ignored_lib) const;
47
48 // Checks whether the provided PC belongs to an instrumented module.
49 bool IsPcInstrumented(uptr pc) const;
50
51 private:
52 struct Lib {
53 char *templ;
54 char *name;
55 char *real_name; // target of symlink
56 bool loaded;
57 };
58
59 struct LibCodeRange {
60 uptr begin;
61 uptr end;
62 };
63
64 inline bool IsInRange(uptr pc, const LibCodeRange &range) const {
65 return (pc >= range.begin && pc < range.end);
66 }
67
68 static const uptr kMaxIgnoredRanges = 128;
69 static const uptr kMaxInstrumentedRanges = 1024;
70 static const uptr kMaxLibs = 1024;
71
72 // Hot part:
73 atomic_uintptr_t ignored_ranges_count_;
74 LibCodeRange ignored_code_ranges_[kMaxIgnoredRanges];
75
76 atomic_uintptr_t instrumented_ranges_count_;
77 LibCodeRange instrumented_code_ranges_[kMaxInstrumentedRanges];
78
79 // Cold part:
80 BlockingMutex mutex_;
81 uptr count_;
82 Lib libs_[kMaxLibs];
83 bool track_instrumented_libs_;
84
85 // Disallow copying of LibIgnore objects.
86 LibIgnore(const LibIgnore&); // not implemented
87 void operator = (const LibIgnore&); // not implemented
88};
89
90inline bool LibIgnore::IsIgnored(uptr pc, bool *pc_in_ignored_lib) const {
91 const uptr n = atomic_load(&ignored_ranges_count_, memory_order_acquire);
92 for (uptr i = 0; i < n; i++) {
93 if (IsInRange(pc, ignored_code_ranges_[i])) {
94 *pc_in_ignored_lib = true;
95 return true;
96 }
97 }
98 *pc_in_ignored_lib = false;
99 if (track_instrumented_libs_ && !IsPcInstrumented(pc))
100 return true;
101 return false;
102}
103
104inline bool LibIgnore::IsPcInstrumented(uptr pc) const {
105 const uptr n = atomic_load(&instrumented_ranges_count_, memory_order_acquire);
106 for (uptr i = 0; i < n; i++) {
107 if (IsInRange(pc, instrumented_code_ranges_[i]))
108 return true;
109 }
110 return false;
111}
112
113} // namespace __sanitizer
114
115#endif // SANITIZER_LIBIGNORE_H
lib/tsan/sanitizer_common/sanitizer_linux.cpp created+2269
...@@ -0,0 +1,2269 @@
1//===-- sanitizer_linux.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 shared between AddressSanitizer and ThreadSanitizer
10// run-time libraries and implements linux-specific functions from
11// sanitizer_libc.h.
12//===----------------------------------------------------------------------===//
13
14#include "sanitizer_platform.h"
15
16#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
17 SANITIZER_OPENBSD || SANITIZER_SOLARIS
18
19#include "sanitizer_common.h"
20#include "sanitizer_flags.h"
21#include "sanitizer_getauxval.h"
22#include "sanitizer_internal_defs.h"
23#include "sanitizer_libc.h"
24#include "sanitizer_linux.h"
25#include "sanitizer_mutex.h"
26#include "sanitizer_placement_new.h"
27#include "sanitizer_procmaps.h"
28
29#if SANITIZER_LINUX && !SANITIZER_GO
30#include <asm/param.h>
31#endif
32
33// For mips64, syscall(__NR_stat) fills the buffer in the 'struct kernel_stat'
34// format. Struct kernel_stat is defined as 'struct stat' in asm/stat.h. To
35// access stat from asm/stat.h, without conflicting with definition in
36// sys/stat.h, we use this trick.
37#if defined(__mips64)
38#include <asm/unistd.h>
39#include <sys/types.h>
40#define stat kernel_stat
41#include <asm/stat.h>
42#undef stat
43#endif
44
45#include <dlfcn.h>
46#include <errno.h>
47#include <fcntl.h>
48#include <link.h>
49#include <pthread.h>
50#include <sched.h>
51#include <signal.h>
52#include <sys/mman.h>
53#include <sys/param.h>
54#if !SANITIZER_SOLARIS
55#include <sys/ptrace.h>
56#endif
57#include <sys/resource.h>
58#include <sys/stat.h>
59#include <sys/syscall.h>
60#include <sys/time.h>
61#include <sys/types.h>
62#if !SANITIZER_OPENBSD
63#include <ucontext.h>
64#endif
65#if SANITIZER_OPENBSD
66#include <sys/futex.h>
67#include <sys/sysctl.h>
68#endif
69#include <unistd.h>
70
71#if SANITIZER_LINUX
72#include <sys/utsname.h>
73#endif
74
75#if SANITIZER_LINUX && !SANITIZER_ANDROID
76#include <sys/personality.h>
77#endif
78
79#if SANITIZER_FREEBSD
80#include <sys/exec.h>
81#include <sys/sysctl.h>
82#include <machine/atomic.h>
83extern "C" {
84// <sys/umtx.h> must be included after <errno.h> and <sys/types.h> on
85// FreeBSD 9.2 and 10.0.
86#include <sys/umtx.h>
87}
88#include <sys/thr.h>
89#endif // SANITIZER_FREEBSD
90
91#if SANITIZER_NETBSD
92#include <limits.h> // For NAME_MAX
93#include <sys/sysctl.h>
94#include <sys/exec.h>
95extern struct ps_strings *__ps_strings;
96#endif // SANITIZER_NETBSD
97
98#if SANITIZER_SOLARIS
99#include <stdlib.h>
100#include <thread.h>
101#define environ _environ
102#endif
103
104extern char **environ;
105
106#if SANITIZER_LINUX
107// <linux/time.h>
108struct kernel_timeval {
109 long tv_sec;
110 long tv_usec;
111};
112
113// <linux/futex.h> is broken on some linux distributions.
114const int FUTEX_WAIT = 0;
115const int FUTEX_WAKE = 1;
116const int FUTEX_PRIVATE_FLAG = 128;
117const int FUTEX_WAIT_PRIVATE = FUTEX_WAIT | FUTEX_PRIVATE_FLAG;
118const int FUTEX_WAKE_PRIVATE = FUTEX_WAKE | FUTEX_PRIVATE_FLAG;
119#endif // SANITIZER_LINUX
120
121// Are we using 32-bit or 64-bit Linux syscalls?
122// x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32
123// but it still needs to use 64-bit syscalls.
124#if SANITIZER_LINUX && (defined(__x86_64__) || defined(__powerpc64__) || \
125 SANITIZER_WORDSIZE == 64)
126# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1
127#else
128# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0
129#endif
130
131// Note : FreeBSD had implemented both
132// Linux and OpenBSD apis, available from
133// future 12.x version most likely
134#if SANITIZER_LINUX && defined(__NR_getrandom)
135# if !defined(GRND_NONBLOCK)
136# define GRND_NONBLOCK 1
137# endif
138# define SANITIZER_USE_GETRANDOM 1
139#else
140# define SANITIZER_USE_GETRANDOM 0
141#endif // SANITIZER_LINUX && defined(__NR_getrandom)
142
143#if SANITIZER_OPENBSD
144# define SANITIZER_USE_GETENTROPY 1
145#else
146# if SANITIZER_FREEBSD && __FreeBSD_version >= 1200000
147# define SANITIZER_USE_GETENTROPY 1
148# else
149# define SANITIZER_USE_GETENTROPY 0
150# endif
151#endif // SANITIZER_USE_GETENTROPY
152
153namespace __sanitizer {
154
155#if SANITIZER_LINUX && defined(__x86_64__)
156#include "sanitizer_syscall_linux_x86_64.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
164
165// --------------- sanitizer_libc.h
166#if !SANITIZER_SOLARIS && !SANITIZER_NETBSD
167#if !SANITIZER_S390 && !SANITIZER_OPENBSD
168uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd,
169 u64 offset) {
170#if SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS
171 return internal_syscall(SYSCALL(mmap), (uptr)addr, length, prot, flags, fd,
172 offset);
173#else
174 // mmap2 specifies file offset in 4096-byte units.
175 CHECK(IsAligned(offset, 4096));
176 return internal_syscall(SYSCALL(mmap2), addr, length, prot, flags, fd,
177 offset / 4096);
178#endif
179}
180#endif // !SANITIZER_S390 && !SANITIZER_OPENBSD
181
182#if !SANITIZER_OPENBSD
183uptr internal_munmap(void *addr, uptr length) {
184 return internal_syscall(SYSCALL(munmap), (uptr)addr, length);
185}
186
187int internal_mprotect(void *addr, uptr length, int prot) {
188 return internal_syscall(SYSCALL(mprotect), (uptr)addr, length, prot);
189}
190#endif
191
192uptr internal_close(fd_t fd) {
193 return internal_syscall(SYSCALL(close), fd);
194}
195
196uptr internal_open(const char *filename, int flags) {
197#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
198 return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags);
199#else
200 return internal_syscall(SYSCALL(open), (uptr)filename, flags);
201#endif
202}
203
204uptr internal_open(const char *filename, int flags, u32 mode) {
205#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
206 return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags,
207 mode);
208#else
209 return internal_syscall(SYSCALL(open), (uptr)filename, flags, mode);
210#endif
211}
212
213uptr internal_read(fd_t fd, void *buf, uptr count) {
214 sptr res;
215 HANDLE_EINTR(res,
216 (sptr)internal_syscall(SYSCALL(read), fd, (uptr)buf, count));
217 return res;
218}
219
220uptr internal_write(fd_t fd, const void *buf, uptr count) {
221 sptr res;
222 HANDLE_EINTR(res,
223 (sptr)internal_syscall(SYSCALL(write), fd, (uptr)buf, count));
224 return res;
225}
226
227uptr internal_ftruncate(fd_t fd, uptr size) {
228 sptr res;
229 HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(ftruncate), fd,
230 (OFF_T)size));
231 return res;
232}
233
234#if !SANITIZER_LINUX_USES_64BIT_SYSCALLS && SANITIZER_LINUX
235static void stat64_to_stat(struct stat64 *in, struct stat *out) {
236 internal_memset(out, 0, sizeof(*out));
237 out->st_dev = in->st_dev;
238 out->st_ino = in->st_ino;
239 out->st_mode = in->st_mode;
240 out->st_nlink = in->st_nlink;
241 out->st_uid = in->st_uid;
242 out->st_gid = in->st_gid;
243 out->st_rdev = in->st_rdev;
244 out->st_size = in->st_size;
245 out->st_blksize = in->st_blksize;
246 out->st_blocks = in->st_blocks;
247 out->st_atime = in->st_atime;
248 out->st_mtime = in->st_mtime;
249 out->st_ctime = in->st_ctime;
250}
251#endif
252
253#if defined(__mips64)
254// Undefine compatibility macros from <sys/stat.h>
255// so that they would not clash with the kernel_stat
256// st_[a|m|c]time fields
257#undef st_atime
258#undef st_mtime
259#undef st_ctime
260#if defined(SANITIZER_ANDROID)
261// Bionic sys/stat.h defines additional macros
262// for compatibility with the old NDKs and
263// they clash with the kernel_stat structure
264// st_[a|m|c]time_nsec fields.
265#undef st_atime_nsec
266#undef st_mtime_nsec
267#undef st_ctime_nsec
268#endif
269static void kernel_stat_to_stat(struct kernel_stat *in, struct stat *out) {
270 internal_memset(out, 0, sizeof(*out));
271 out->st_dev = in->st_dev;
272 out->st_ino = in->st_ino;
273 out->st_mode = in->st_mode;
274 out->st_nlink = in->st_nlink;
275 out->st_uid = in->st_uid;
276 out->st_gid = in->st_gid;
277 out->st_rdev = in->st_rdev;
278 out->st_size = in->st_size;
279 out->st_blksize = in->st_blksize;
280 out->st_blocks = in->st_blocks;
281#if defined(__USE_MISC) || \
282 defined(__USE_XOPEN2K8) || \
283 defined(SANITIZER_ANDROID)
284 out->st_atim.tv_sec = in->st_atime;
285 out->st_atim.tv_nsec = in->st_atime_nsec;
286 out->st_mtim.tv_sec = in->st_mtime;
287 out->st_mtim.tv_nsec = in->st_mtime_nsec;
288 out->st_ctim.tv_sec = in->st_ctime;
289 out->st_ctim.tv_nsec = in->st_ctime_nsec;
290#else
291 out->st_atime = in->st_atime;
292 out->st_atimensec = in->st_atime_nsec;
293 out->st_mtime = in->st_mtime;
294 out->st_mtimensec = in->st_mtime_nsec;
295 out->st_ctime = in->st_ctime;
296 out->st_atimensec = in->st_ctime_nsec;
297#endif
298}
299#endif
300
301uptr internal_stat(const char *path, void *buf) {
302#if SANITIZER_FREEBSD || SANITIZER_OPENBSD
303 return internal_syscall(SYSCALL(fstatat), AT_FDCWD, (uptr)path, (uptr)buf, 0);
304#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
305 return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf,
306 0);
307#elif SANITIZER_LINUX_USES_64BIT_SYSCALLS
308# if defined(__mips64)
309 // For mips64, stat syscall fills buffer in the format of kernel_stat
310 struct kernel_stat kbuf;
311 int res = internal_syscall(SYSCALL(stat), path, &kbuf);
312 kernel_stat_to_stat(&kbuf, (struct stat *)buf);
313 return res;
314# else
315 return internal_syscall(SYSCALL(stat), (uptr)path, (uptr)buf);
316# endif
317#else
318 struct stat64 buf64;
319 int res = internal_syscall(SYSCALL(stat64), path, &buf64);
320 stat64_to_stat(&buf64, (struct stat *)buf);
321 return res;
322#endif
323}
324
325uptr internal_lstat(const char *path, void *buf) {
326#if SANITIZER_FREEBSD || SANITIZER_OPENBSD
327 return internal_syscall(SYSCALL(fstatat), AT_FDCWD, (uptr)path, (uptr)buf,
328 AT_SYMLINK_NOFOLLOW);
329#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
330 return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf,
331 AT_SYMLINK_NOFOLLOW);
332#elif SANITIZER_LINUX_USES_64BIT_SYSCALLS
333# if SANITIZER_MIPS64
334 // For mips64, lstat syscall fills buffer in the format of kernel_stat
335 struct kernel_stat kbuf;
336 int res = internal_syscall(SYSCALL(lstat), path, &kbuf);
337 kernel_stat_to_stat(&kbuf, (struct stat *)buf);
338 return res;
339# else
340 return internal_syscall(SYSCALL(lstat), (uptr)path, (uptr)buf);
341# endif
342#else
343 struct stat64 buf64;
344 int res = internal_syscall(SYSCALL(lstat64), path, &buf64);
345 stat64_to_stat(&buf64, (struct stat *)buf);
346 return res;
347#endif
348}
349
350uptr internal_fstat(fd_t fd, void *buf) {
351#if SANITIZER_FREEBSD || SANITIZER_OPENBSD || \
352 SANITIZER_LINUX_USES_64BIT_SYSCALLS
353#if SANITIZER_MIPS64 && !SANITIZER_OPENBSD
354 // For mips64, fstat syscall fills buffer in the format of kernel_stat
355 struct kernel_stat kbuf;
356 int res = internal_syscall(SYSCALL(fstat), fd, &kbuf);
357 kernel_stat_to_stat(&kbuf, (struct stat *)buf);
358 return res;
359# else
360 return internal_syscall(SYSCALL(fstat), fd, (uptr)buf);
361# endif
362#else
363 struct stat64 buf64;
364 int res = internal_syscall(SYSCALL(fstat64), fd, &buf64);
365 stat64_to_stat(&buf64, (struct stat *)buf);
366 return res;
367#endif
368}
369
370uptr internal_filesize(fd_t fd) {
371 struct stat st;
372 if (internal_fstat(fd, &st))
373 return -1;
374 return (uptr)st.st_size;
375}
376
377uptr internal_dup(int oldfd) {
378 return internal_syscall(SYSCALL(dup), oldfd);
379}
380
381uptr internal_dup2(int oldfd, int newfd) {
382#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
383 return internal_syscall(SYSCALL(dup3), oldfd, newfd, 0);
384#else
385 return internal_syscall(SYSCALL(dup2), oldfd, newfd);
386#endif
387}
388
389uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
390#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
391 return internal_syscall(SYSCALL(readlinkat), AT_FDCWD, (uptr)path, (uptr)buf,
392 bufsize);
393#elif SANITIZER_OPENBSD
394 return internal_syscall(SYSCALL(readlinkat), AT_FDCWD, (uptr)path, (uptr)buf,
395 bufsize);
396#else
397 return internal_syscall(SYSCALL(readlink), (uptr)path, (uptr)buf, bufsize);
398#endif
399}
400
401uptr internal_unlink(const char *path) {
402#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS || SANITIZER_OPENBSD
403 return internal_syscall(SYSCALL(unlinkat), AT_FDCWD, (uptr)path, 0);
404#else
405 return internal_syscall(SYSCALL(unlink), (uptr)path);
406#endif
407}
408
409uptr internal_rename(const char *oldpath, const char *newpath) {
410#if defined(__riscv)
411 return internal_syscall(SYSCALL(renameat2), AT_FDCWD, (uptr)oldpath, AT_FDCWD,
412 (uptr)newpath, 0);
413#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS || SANITIZER_OPENBSD
414 return internal_syscall(SYSCALL(renameat), AT_FDCWD, (uptr)oldpath, AT_FDCWD,
415 (uptr)newpath);
416#else
417 return internal_syscall(SYSCALL(rename), (uptr)oldpath, (uptr)newpath);
418#endif
419}
420
421uptr internal_sched_yield() {
422 return internal_syscall(SYSCALL(sched_yield));
423}
424
425void internal__exit(int exitcode) {
426#if SANITIZER_FREEBSD || SANITIZER_OPENBSD
427 internal_syscall(SYSCALL(exit), exitcode);
428#else
429 internal_syscall(SYSCALL(exit_group), exitcode);
430#endif
431 Die(); // Unreachable.
432}
433
434unsigned int internal_sleep(unsigned int seconds) {
435 struct timespec ts;
436 ts.tv_sec = seconds;
437 ts.tv_nsec = 0;
438 int res = internal_syscall(SYSCALL(nanosleep), &ts, &ts);
439 if (res) return ts.tv_sec;
440 return 0;
441}
442
443uptr internal_execve(const char *filename, char *const argv[],
444 char *const envp[]) {
445 return internal_syscall(SYSCALL(execve), (uptr)filename, (uptr)argv,
446 (uptr)envp);
447}
448#endif // !SANITIZER_SOLARIS && !SANITIZER_NETBSD
449
450// ----------------- sanitizer_common.h
451bool FileExists(const char *filename) {
452 if (ShouldMockFailureToOpen(filename))
453 return false;
454 struct stat st;
455#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
456 if (internal_syscall(SYSCALL(newfstatat), AT_FDCWD, filename, &st, 0))
457#else
458 if (internal_stat(filename, &st))
459#endif
460 return false;
461 // Sanity check: filename is a regular file.
462 return S_ISREG(st.st_mode);
463}
464
465#if !SANITIZER_NETBSD
466tid_t GetTid() {
467#if SANITIZER_FREEBSD
468 long Tid;
469 thr_self(&Tid);
470 return Tid;
471#elif SANITIZER_OPENBSD
472 return internal_syscall(SYSCALL(getthrid));
473#elif SANITIZER_SOLARIS
474 return thr_self();
475#else
476 return internal_syscall(SYSCALL(gettid));
477#endif
478}
479
480int TgKill(pid_t pid, tid_t tid, int sig) {
481#if SANITIZER_LINUX
482 return internal_syscall(SYSCALL(tgkill), pid, tid, sig);
483#elif SANITIZER_FREEBSD
484 return internal_syscall(SYSCALL(thr_kill2), pid, tid, sig);
485#elif SANITIZER_OPENBSD
486 (void)pid;
487 return internal_syscall(SYSCALL(thrkill), tid, sig, nullptr);
488#elif SANITIZER_SOLARIS
489 (void)pid;
490 return thr_kill(tid, sig);
491#endif
492}
493#endif
494
495#if !SANITIZER_SOLARIS && !SANITIZER_NETBSD
496u64 NanoTime() {
497#if SANITIZER_FREEBSD || SANITIZER_OPENBSD
498 timeval tv;
499#else
500 kernel_timeval tv;
501#endif
502 internal_memset(&tv, 0, sizeof(tv));
503 internal_syscall(SYSCALL(gettimeofday), &tv, 0);
504 return (u64)tv.tv_sec * 1000*1000*1000 + tv.tv_usec * 1000;
505}
506
507uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp) {
508 return internal_syscall(SYSCALL(clock_gettime), clk_id, tp);
509}
510#endif // !SANITIZER_SOLARIS && !SANITIZER_NETBSD
511
512// Like getenv, but reads env directly from /proc (on Linux) or parses the
513// 'environ' array (on some others) and does not use libc. This function
514// should be called first inside __asan_init.
515const char *GetEnv(const char *name) {
516#if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_OPENBSD || \
517 SANITIZER_SOLARIS
518 if (::environ != 0) {
519 uptr NameLen = internal_strlen(name);
520 for (char **Env = ::environ; *Env != 0; Env++) {
521 if (internal_strncmp(*Env, name, NameLen) == 0 && (*Env)[NameLen] == '=')
522 return (*Env) + NameLen + 1;
523 }
524 }
525 return 0; // Not found.
526#elif SANITIZER_LINUX
527 static char *environ;
528 static uptr len;
529 static bool inited;
530 if (!inited) {
531 inited = true;
532 uptr environ_size;
533 if (!ReadFileToBuffer("/proc/self/environ", &environ, &environ_size, &len))
534 environ = nullptr;
535 }
536 if (!environ || len == 0) return nullptr;
537 uptr namelen = internal_strlen(name);
538 const char *p = environ;
539 while (*p != '\0') { // will happen at the \0\0 that terminates the buffer
540 // proc file has the format NAME=value\0NAME=value\0NAME=value\0...
541 const char* endp =
542 (char*)internal_memchr(p, '\0', len - (p - environ));
543 if (!endp) // this entry isn't NUL terminated
544 return nullptr;
545 else if (!internal_memcmp(p, name, namelen) && p[namelen] == '=') // Match.
546 return p + namelen + 1; // point after =
547 p = endp + 1;
548 }
549 return nullptr; // Not found.
550#else
551#error "Unsupported platform"
552#endif
553}
554
555#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD && !SANITIZER_OPENBSD && \
556 !SANITIZER_GO
557extern "C" {
558SANITIZER_WEAK_ATTRIBUTE extern void *__libc_stack_end;
559}
560#endif
561
562#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD && \
563 !SANITIZER_OPENBSD
564static void ReadNullSepFileToArray(const char *path, char ***arr,
565 int arr_size) {
566 char *buff;
567 uptr buff_size;
568 uptr buff_len;
569 *arr = (char **)MmapOrDie(arr_size * sizeof(char *), "NullSepFileArray");
570 if (!ReadFileToBuffer(path, &buff, &buff_size, &buff_len, 1024 * 1024)) {
571 (*arr)[0] = nullptr;
572 return;
573 }
574 (*arr)[0] = buff;
575 int count, i;
576 for (count = 1, i = 1; ; i++) {
577 if (buff[i] == 0) {
578 if (buff[i+1] == 0) break;
579 (*arr)[count] = &buff[i+1];
580 CHECK_LE(count, arr_size - 1); // FIXME: make this more flexible.
581 count++;
582 }
583 }
584 (*arr)[count] = nullptr;
585}
586#endif
587
588#if !SANITIZER_OPENBSD
589static void GetArgsAndEnv(char ***argv, char ***envp) {
590#if SANITIZER_FREEBSD
591 // On FreeBSD, retrieving the argument and environment arrays is done via the
592 // kern.ps_strings sysctl, which returns a pointer to a structure containing
593 // this information. See also <sys/exec.h>.
594 ps_strings *pss;
595 uptr sz = sizeof(pss);
596 if (internal_sysctlbyname("kern.ps_strings", &pss, &sz, NULL, 0) == -1) {
597 Printf("sysctl kern.ps_strings failed\n");
598 Die();
599 }
600 *argv = pss->ps_argvstr;
601 *envp = pss->ps_envstr;
602#elif SANITIZER_NETBSD
603 *argv = __ps_strings->ps_argvstr;
604 *envp = __ps_strings->ps_envstr;
605#else // SANITIZER_FREEBSD
606#if !SANITIZER_GO
607 if (&__libc_stack_end) {
608 uptr* stack_end = (uptr*)__libc_stack_end;
609 // Normally argc can be obtained from *stack_end, however, on ARM glibc's
610 // _start clobbers it:
611 // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/arm/start.S;hb=refs/heads/release/2.31/master#l75
612 // Do not special-case ARM and infer argc from argv everywhere.
613 int argc = 0;
614 while (stack_end[argc + 1]) argc++;
615 *argv = (char**)(stack_end + 1);
616 *envp = (char**)(stack_end + argc + 2);
617 } else {
618#endif // !SANITIZER_GO
619 static const int kMaxArgv = 2000, kMaxEnvp = 2000;
620 ReadNullSepFileToArray("/proc/self/cmdline", argv, kMaxArgv);
621 ReadNullSepFileToArray("/proc/self/environ", envp, kMaxEnvp);
622#if !SANITIZER_GO
623 }
624#endif // !SANITIZER_GO
625#endif // SANITIZER_FREEBSD
626}
627
628char **GetArgv() {
629 char **argv, **envp;
630 GetArgsAndEnv(&argv, &envp);
631 return argv;
632}
633
634char **GetEnviron() {
635 char **argv, **envp;
636 GetArgsAndEnv(&argv, &envp);
637 return envp;
638}
639
640#endif // !SANITIZER_OPENBSD
641
642#if !SANITIZER_SOLARIS
643enum MutexState {
644 MtxUnlocked = 0,
645 MtxLocked = 1,
646 MtxSleeping = 2
647};
648
649BlockingMutex::BlockingMutex() {
650 internal_memset(this, 0, sizeof(*this));
651}
652
653void BlockingMutex::Lock() {
654 CHECK_EQ(owner_, 0);
655 atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
656 if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked)
657 return;
658 while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked) {
659#if SANITIZER_FREEBSD
660 _umtx_op(m, UMTX_OP_WAIT_UINT, MtxSleeping, 0, 0);
661#elif SANITIZER_NETBSD
662 sched_yield(); /* No userspace futex-like synchronization */
663#else
664 internal_syscall(SYSCALL(futex), (uptr)m, FUTEX_WAIT_PRIVATE, MtxSleeping,
665 0, 0, 0);
666#endif
667 }
668}
669
670void BlockingMutex::Unlock() {
671 atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
672 u32 v = atomic_exchange(m, MtxUnlocked, memory_order_release);
673 CHECK_NE(v, MtxUnlocked);
674 if (v == MtxSleeping) {
675#if SANITIZER_FREEBSD
676 _umtx_op(m, UMTX_OP_WAKE, 1, 0, 0);
677#elif SANITIZER_NETBSD
678 /* No userspace futex-like synchronization */
679#else
680 internal_syscall(SYSCALL(futex), (uptr)m, FUTEX_WAKE_PRIVATE, 1, 0, 0, 0);
681#endif
682 }
683}
684
685void BlockingMutex::CheckLocked() {
686 atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
687 CHECK_NE(MtxUnlocked, atomic_load(m, memory_order_relaxed));
688}
689#endif // !SANITIZER_SOLARIS
690
691// ----------------- sanitizer_linux.h
692// The actual size of this structure is specified by d_reclen.
693// Note that getdents64 uses a different structure format. We only provide the
694// 32-bit syscall here.
695#if SANITIZER_NETBSD
696// Not used
697#elif SANITIZER_OPENBSD
698// struct dirent is different for Linux and us. At this moment, we use only
699// d_fileno (Linux call this d_ino), d_reclen, and d_name.
700struct linux_dirent {
701 u64 d_ino; // d_fileno
702 u16 d_reclen;
703 u16 d_namlen; // not used
704 u8 d_type; // not used
705 char d_name[NAME_MAX + 1];
706};
707#else
708struct linux_dirent {
709#if SANITIZER_X32 || defined(__aarch64__)
710 u64 d_ino;
711 u64 d_off;
712#else
713 unsigned long d_ino;
714 unsigned long d_off;
715#endif
716 unsigned short d_reclen;
717#ifdef __aarch64__
718 unsigned char d_type;
719#endif
720 char d_name[256];
721};
722#endif
723
724#if !SANITIZER_SOLARIS && !SANITIZER_NETBSD
725// Syscall wrappers.
726uptr internal_ptrace(int request, int pid, void *addr, void *data) {
727 return internal_syscall(SYSCALL(ptrace), request, pid, (uptr)addr,
728 (uptr)data);
729}
730
731uptr internal_waitpid(int pid, int *status, int options) {
732 return internal_syscall(SYSCALL(wait4), pid, (uptr)status, options,
733 0 /* rusage */);
734}
735
736uptr internal_getpid() {
737 return internal_syscall(SYSCALL(getpid));
738}
739
740uptr internal_getppid() {
741 return internal_syscall(SYSCALL(getppid));
742}
743
744int internal_dlinfo(void *handle, int request, void *p) {
745#if SANITIZER_FREEBSD
746 return dlinfo(handle, request, p);
747#else
748 UNIMPLEMENTED();
749#endif
750}
751
752uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) {
753#if SANITIZER_FREEBSD
754 return internal_syscall(SYSCALL(getdirentries), fd, (uptr)dirp, count, NULL);
755#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
756 return internal_syscall(SYSCALL(getdents64), fd, (uptr)dirp, count);
757#else
758 return internal_syscall(SYSCALL(getdents), fd, (uptr)dirp, count);
759#endif
760}
761
762uptr internal_lseek(fd_t fd, OFF_T offset, int whence) {
763 return internal_syscall(SYSCALL(lseek), fd, offset, whence);
764}
765
766#if SANITIZER_LINUX
767uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) {
768 return internal_syscall(SYSCALL(prctl), option, arg2, arg3, arg4, arg5);
769}
770#endif
771
772uptr internal_sigaltstack(const void *ss, void *oss) {
773 return internal_syscall(SYSCALL(sigaltstack), (uptr)ss, (uptr)oss);
774}
775
776int internal_fork() {
777#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
778 return internal_syscall(SYSCALL(clone), SIGCHLD, 0);
779#else
780 return internal_syscall(SYSCALL(fork));
781#endif
782}
783
784#if SANITIZER_FREEBSD || SANITIZER_OPENBSD
785int internal_sysctl(const int *name, unsigned int namelen, void *oldp,
786 uptr *oldlenp, const void *newp, uptr newlen) {
787#if SANITIZER_OPENBSD
788 return sysctl(name, namelen, oldp, (size_t *)oldlenp, (void *)newp,
789 (size_t)newlen);
790#else
791 return internal_syscall(SYSCALL(__sysctl), name, namelen, oldp,
792 (size_t *)oldlenp, newp, (size_t)newlen);
793#endif
794}
795
796#if SANITIZER_FREEBSD
797int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp,
798 const void *newp, uptr newlen) {
799 static decltype(sysctlbyname) *real = nullptr;
800 if (!real)
801 real = (decltype(sysctlbyname) *)dlsym(RTLD_NEXT, "sysctlbyname");
802 CHECK(real);
803 return real(sname, oldp, (size_t *)oldlenp, newp, (size_t)newlen);
804}
805#endif
806#endif
807
808#if SANITIZER_LINUX
809#define SA_RESTORER 0x04000000
810// Doesn't set sa_restorer if the caller did not set it, so use with caution
811//(see below).
812int internal_sigaction_norestorer(int signum, const void *act, void *oldact) {
813 __sanitizer_kernel_sigaction_t k_act, k_oldact;
814 internal_memset(&k_act, 0, sizeof(__sanitizer_kernel_sigaction_t));
815 internal_memset(&k_oldact, 0, sizeof(__sanitizer_kernel_sigaction_t));
816 const __sanitizer_sigaction *u_act = (const __sanitizer_sigaction *)act;
817 __sanitizer_sigaction *u_oldact = (__sanitizer_sigaction *)oldact;
818 if (u_act) {
819 k_act.handler = u_act->handler;
820 k_act.sigaction = u_act->sigaction;
821 internal_memcpy(&k_act.sa_mask, &u_act->sa_mask,
822 sizeof(__sanitizer_kernel_sigset_t));
823 // Without SA_RESTORER kernel ignores the calls (probably returns EINVAL).
824 k_act.sa_flags = u_act->sa_flags | SA_RESTORER;
825 // FIXME: most often sa_restorer is unset, however the kernel requires it
826 // to point to a valid signal restorer that calls the rt_sigreturn syscall.
827 // If sa_restorer passed to the kernel is NULL, the program may crash upon
828 // signal delivery or fail to unwind the stack in the signal handler.
829 // libc implementation of sigaction() passes its own restorer to
830 // rt_sigaction, so we need to do the same (we'll need to reimplement the
831 // restorers; for x86_64 the restorer address can be obtained from
832 // oldact->sa_restorer upon a call to sigaction(xxx, NULL, oldact).
833#if !SANITIZER_ANDROID || !SANITIZER_MIPS32
834 k_act.sa_restorer = u_act->sa_restorer;
835#endif
836 }
837
838 uptr result = internal_syscall(SYSCALL(rt_sigaction), (uptr)signum,
839 (uptr)(u_act ? &k_act : nullptr),
840 (uptr)(u_oldact ? &k_oldact : nullptr),
841 (uptr)sizeof(__sanitizer_kernel_sigset_t));
842
843 if ((result == 0) && u_oldact) {
844 u_oldact->handler = k_oldact.handler;
845 u_oldact->sigaction = k_oldact.sigaction;
846 internal_memcpy(&u_oldact->sa_mask, &k_oldact.sa_mask,
847 sizeof(__sanitizer_kernel_sigset_t));
848 u_oldact->sa_flags = k_oldact.sa_flags;
849#if !SANITIZER_ANDROID || !SANITIZER_MIPS32
850 u_oldact->sa_restorer = k_oldact.sa_restorer;
851#endif
852 }
853 return result;
854}
855#endif // SANITIZER_LINUX
856
857uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set,
858 __sanitizer_sigset_t *oldset) {
859#if SANITIZER_FREEBSD || SANITIZER_OPENBSD
860 return internal_syscall(SYSCALL(sigprocmask), how, set, oldset);
861#else
862 __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set;
863 __sanitizer_kernel_sigset_t *k_oldset = (__sanitizer_kernel_sigset_t *)oldset;
864 return internal_syscall(SYSCALL(rt_sigprocmask), (uptr)how, (uptr)k_set,
865 (uptr)k_oldset, sizeof(__sanitizer_kernel_sigset_t));
866#endif
867}
868
869void internal_sigfillset(__sanitizer_sigset_t *set) {
870 internal_memset(set, 0xff, sizeof(*set));
871}
872
873void internal_sigemptyset(__sanitizer_sigset_t *set) {
874 internal_memset(set, 0, sizeof(*set));
875}
876
877#if SANITIZER_LINUX
878void internal_sigdelset(__sanitizer_sigset_t *set, int signum) {
879 signum -= 1;
880 CHECK_GE(signum, 0);
881 CHECK_LT(signum, sizeof(*set) * 8);
882 __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set;
883 const uptr idx = signum / (sizeof(k_set->sig[0]) * 8);
884 const uptr bit = signum % (sizeof(k_set->sig[0]) * 8);
885 k_set->sig[idx] &= ~(1 << bit);
886}
887
888bool internal_sigismember(__sanitizer_sigset_t *set, int signum) {
889 signum -= 1;
890 CHECK_GE(signum, 0);
891 CHECK_LT(signum, sizeof(*set) * 8);
892 __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set;
893 const uptr idx = signum / (sizeof(k_set->sig[0]) * 8);
894 const uptr bit = signum % (sizeof(k_set->sig[0]) * 8);
895 return k_set->sig[idx] & (1 << bit);
896}
897#elif SANITIZER_FREEBSD
898void internal_sigdelset(__sanitizer_sigset_t *set, int signum) {
899 sigset_t *rset = reinterpret_cast<sigset_t *>(set);
900 sigdelset(rset, signum);
901}
902
903bool internal_sigismember(__sanitizer_sigset_t *set, int signum) {
904 sigset_t *rset = reinterpret_cast<sigset_t *>(set);
905 return sigismember(rset, signum);
906}
907#endif
908#endif // !SANITIZER_SOLARIS
909
910#if !SANITIZER_NETBSD
911// ThreadLister implementation.
912ThreadLister::ThreadLister(pid_t pid) : pid_(pid), buffer_(4096) {
913 char task_directory_path[80];
914 internal_snprintf(task_directory_path, sizeof(task_directory_path),
915 "/proc/%d/task/", pid);
916 descriptor_ = internal_open(task_directory_path, O_RDONLY | O_DIRECTORY);
917 if (internal_iserror(descriptor_)) {
918 Report("Can't open /proc/%d/task for reading.\n", pid);
919 }
920}
921
922ThreadLister::Result ThreadLister::ListThreads(
923 InternalMmapVector<tid_t> *threads) {
924 if (internal_iserror(descriptor_))
925 return Error;
926 internal_lseek(descriptor_, 0, SEEK_SET);
927 threads->clear();
928
929 Result result = Ok;
930 for (bool first_read = true;; first_read = false) {
931 // Resize to max capacity if it was downsized by IsAlive.
932 buffer_.resize(buffer_.capacity());
933 CHECK_GE(buffer_.size(), 4096);
934 uptr read = internal_getdents(
935 descriptor_, (struct linux_dirent *)buffer_.data(), buffer_.size());
936 if (!read)
937 return result;
938 if (internal_iserror(read)) {
939 Report("Can't read directory entries from /proc/%d/task.\n", pid_);
940 return Error;
941 }
942
943 for (uptr begin = (uptr)buffer_.data(), end = begin + read; begin < end;) {
944 struct linux_dirent *entry = (struct linux_dirent *)begin;
945 begin += entry->d_reclen;
946 if (entry->d_ino == 1) {
947 // Inode 1 is for bad blocks and also can be a reason for early return.
948 // Should be emitted if kernel tried to output terminating thread.
949 // See proc_task_readdir implementation in Linux.
950 result = Incomplete;
951 }
952 if (entry->d_ino && *entry->d_name >= '0' && *entry->d_name <= '9')
953 threads->push_back(internal_atoll(entry->d_name));
954 }
955
956 // Now we are going to detect short-read or early EOF. In such cases Linux
957 // can return inconsistent list with missing alive threads.
958 // Code will just remember that the list can be incomplete but it will
959 // continue reads to return as much as possible.
960 if (!first_read) {
961 // The first one was a short-read by definition.
962 result = Incomplete;
963 } else if (read > buffer_.size() - 1024) {
964 // Read was close to the buffer size. So double the size and assume the
965 // worst.
966 buffer_.resize(buffer_.size() * 2);
967 result = Incomplete;
968 } else if (!threads->empty() && !IsAlive(threads->back())) {
969 // Maybe Linux early returned from read on terminated thread (!pid_alive)
970 // and failed to restore read position.
971 // See next_tid and proc_task_instantiate in Linux.
972 result = Incomplete;
973 }
974 }
975}
976
977bool ThreadLister::IsAlive(int tid) {
978 // /proc/%d/task/%d/status uses same call to detect alive threads as
979 // proc_task_readdir. See task_state implementation in Linux.
980 char path[80];
981 internal_snprintf(path, sizeof(path), "/proc/%d/task/%d/status", pid_, tid);
982 if (!ReadFileToVector(path, &buffer_) || buffer_.empty())
983 return false;
984 buffer_.push_back(0);
985 static const char kPrefix[] = "\nPPid:";
986 const char *field = internal_strstr(buffer_.data(), kPrefix);
987 if (!field)
988 return false;
989 field += internal_strlen(kPrefix);
990 return (int)internal_atoll(field) != 0;
991}
992
993ThreadLister::~ThreadLister() {
994 if (!internal_iserror(descriptor_))
995 internal_close(descriptor_);
996}
997#endif
998
999#if SANITIZER_WORDSIZE == 32
1000// Take care of unusable kernel area in top gigabyte.
1001static uptr GetKernelAreaSize() {
1002#if SANITIZER_LINUX && !SANITIZER_X32
1003 const uptr gbyte = 1UL << 30;
1004
1005 // Firstly check if there are writable segments
1006 // mapped to top gigabyte (e.g. stack).
1007 MemoryMappingLayout proc_maps(/*cache_enabled*/true);
1008 if (proc_maps.Error())
1009 return 0;
1010 MemoryMappedSegment segment;
1011 while (proc_maps.Next(&segment)) {
1012 if ((segment.end >= 3 * gbyte) && segment.IsWritable()) return 0;
1013 }
1014
1015#if !SANITIZER_ANDROID
1016 // Even if nothing is mapped, top Gb may still be accessible
1017 // if we are running on 64-bit kernel.
1018 // Uname may report misleading results if personality type
1019 // is modified (e.g. under schroot) so check this as well.
1020 struct utsname uname_info;
1021 int pers = personality(0xffffffffUL);
1022 if (!(pers & PER_MASK) && internal_uname(&uname_info) == 0 &&
1023 internal_strstr(uname_info.machine, "64"))
1024 return 0;
1025#endif // SANITIZER_ANDROID
1026
1027 // Top gigabyte is reserved for kernel.
1028 return gbyte;
1029#else
1030 return 0;
1031#endif // SANITIZER_LINUX && !SANITIZER_X32
1032}
1033#endif // SANITIZER_WORDSIZE == 32
1034
1035uptr GetMaxVirtualAddress() {
1036#if (SANITIZER_NETBSD || SANITIZER_OPENBSD) && defined(__x86_64__)
1037 return 0x7f7ffffff000ULL; // (0x00007f8000000000 - PAGE_SIZE)
1038#elif SANITIZER_WORDSIZE == 64
1039# if defined(__powerpc64__) || defined(__aarch64__)
1040 // On PowerPC64 we have two different address space layouts: 44- and 46-bit.
1041 // We somehow need to figure out which one we are using now and choose
1042 // one of 0x00000fffffffffffUL and 0x00003fffffffffffUL.
1043 // Note that with 'ulimit -s unlimited' the stack is moved away from the top
1044 // of the address space, so simply checking the stack address is not enough.
1045 // This should (does) work for both PowerPC64 Endian modes.
1046 // Similarly, aarch64 has multiple address space layouts: 39, 42 and 47-bit.
1047 return (1ULL << (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1)) - 1;
1048# elif defined(__mips64)
1049 return (1ULL << 40) - 1; // 0x000000ffffffffffUL;
1050# elif defined(__s390x__)
1051 return (1ULL << 53) - 1; // 0x001fffffffffffffUL;
1052#elif defined(__sparc__)
1053 return ~(uptr)0;
1054# else
1055 return (1ULL << 47) - 1; // 0x00007fffffffffffUL;
1056# endif
1057#else // SANITIZER_WORDSIZE == 32
1058# if defined(__s390__)
1059 return (1ULL << 31) - 1; // 0x7fffffff;
1060# else
1061 return (1ULL << 32) - 1; // 0xffffffff;
1062# endif
1063#endif // SANITIZER_WORDSIZE
1064}
1065
1066uptr GetMaxUserVirtualAddress() {
1067 uptr addr = GetMaxVirtualAddress();
1068#if SANITIZER_WORDSIZE == 32 && !defined(__s390__)
1069 if (!common_flags()->full_address_space)
1070 addr -= GetKernelAreaSize();
1071 CHECK_LT(reinterpret_cast<uptr>(&addr), addr);
1072#endif
1073 return addr;
1074}
1075
1076#if !SANITIZER_ANDROID
1077uptr GetPageSize() {
1078#if SANITIZER_LINUX && (defined(__x86_64__) || defined(__i386__)) && \
1079 defined(EXEC_PAGESIZE)
1080 return EXEC_PAGESIZE;
1081#elif SANITIZER_FREEBSD || SANITIZER_NETBSD
1082// Use sysctl as sysconf can trigger interceptors internally.
1083 int pz = 0;
1084 uptr pzl = sizeof(pz);
1085 int mib[2] = {CTL_HW, HW_PAGESIZE};
1086 int rv = internal_sysctl(mib, 2, &pz, &pzl, nullptr, 0);
1087 CHECK_EQ(rv, 0);
1088 return (uptr)pz;
1089#elif SANITIZER_USE_GETAUXVAL
1090 return getauxval(AT_PAGESZ);
1091#else
1092 return sysconf(_SC_PAGESIZE); // EXEC_PAGESIZE may not be trustworthy.
1093#endif
1094}
1095#endif // !SANITIZER_ANDROID
1096
1097#if !SANITIZER_OPENBSD
1098uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
1099#if SANITIZER_SOLARIS
1100 const char *default_module_name = getexecname();
1101 CHECK_NE(default_module_name, NULL);
1102 return internal_snprintf(buf, buf_len, "%s", default_module_name);
1103#else
1104#if SANITIZER_FREEBSD || SANITIZER_NETBSD
1105#if SANITIZER_FREEBSD
1106 const int Mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
1107#else
1108 const int Mib[4] = {CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME};
1109#endif
1110 const char *default_module_name = "kern.proc.pathname";
1111 uptr Size = buf_len;
1112 bool IsErr =
1113 (internal_sysctl(Mib, ARRAY_SIZE(Mib), buf, &Size, NULL, 0) != 0);
1114 int readlink_error = IsErr ? errno : 0;
1115 uptr module_name_len = Size;
1116#else
1117 const char *default_module_name = "/proc/self/exe";
1118 uptr module_name_len = internal_readlink(
1119 default_module_name, buf, buf_len);
1120 int readlink_error;
1121 bool IsErr = internal_iserror(module_name_len, &readlink_error);
1122#endif // SANITIZER_SOLARIS
1123 if (IsErr) {
1124 // We can't read binary name for some reason, assume it's unknown.
1125 Report("WARNING: reading executable name failed with errno %d, "
1126 "some stack frames may not be symbolized\n", readlink_error);
1127 module_name_len = internal_snprintf(buf, buf_len, "%s",
1128 default_module_name);
1129 CHECK_LT(module_name_len, buf_len);
1130 }
1131 return module_name_len;
1132#endif
1133}
1134#endif // !SANITIZER_OPENBSD
1135
1136uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len) {
1137#if SANITIZER_LINUX
1138 char *tmpbuf;
1139 uptr tmpsize;
1140 uptr tmplen;
1141 if (ReadFileToBuffer("/proc/self/cmdline", &tmpbuf, &tmpsize, &tmplen,
1142 1024 * 1024)) {
1143 internal_strncpy(buf, tmpbuf, buf_len);
1144 UnmapOrDie(tmpbuf, tmpsize);
1145 return internal_strlen(buf);
1146 }
1147#endif
1148 return ReadBinaryName(buf, buf_len);
1149}
1150
1151// Match full names of the form /path/to/base_name{-,.}*
1152bool LibraryNameIs(const char *full_name, const char *base_name) {
1153 const char *name = full_name;
1154 // Strip path.
1155 while (*name != '\0') name++;
1156 while (name > full_name && *name != '/') name--;
1157 if (*name == '/') name++;
1158 uptr base_name_length = internal_strlen(base_name);
1159 if (internal_strncmp(name, base_name, base_name_length)) return false;
1160 return (name[base_name_length] == '-' || name[base_name_length] == '.');
1161}
1162
1163#if !SANITIZER_ANDROID
1164// Call cb for each region mapped by map.
1165void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)) {
1166 CHECK_NE(map, nullptr);
1167#if !SANITIZER_FREEBSD && !SANITIZER_OPENBSD
1168 typedef ElfW(Phdr) Elf_Phdr;
1169 typedef ElfW(Ehdr) Elf_Ehdr;
1170#endif // !SANITIZER_FREEBSD && !SANITIZER_OPENBSD
1171 char *base = (char *)map->l_addr;
1172 Elf_Ehdr *ehdr = (Elf_Ehdr *)base;
1173 char *phdrs = base + ehdr->e_phoff;
1174 char *phdrs_end = phdrs + ehdr->e_phnum * ehdr->e_phentsize;
1175
1176 // Find the segment with the minimum base so we can "relocate" the p_vaddr
1177 // fields. Typically ET_DYN objects (DSOs) have base of zero and ET_EXEC
1178 // objects have a non-zero base.
1179 uptr preferred_base = (uptr)-1;
1180 for (char *iter = phdrs; iter != phdrs_end; iter += ehdr->e_phentsize) {
1181 Elf_Phdr *phdr = (Elf_Phdr *)iter;
1182 if (phdr->p_type == PT_LOAD && preferred_base > (uptr)phdr->p_vaddr)
1183 preferred_base = (uptr)phdr->p_vaddr;
1184 }
1185
1186 // Compute the delta from the real base to get a relocation delta.
1187 sptr delta = (uptr)base - preferred_base;
1188 // Now we can figure out what the loader really mapped.
1189 for (char *iter = phdrs; iter != phdrs_end; iter += ehdr->e_phentsize) {
1190 Elf_Phdr *phdr = (Elf_Phdr *)iter;
1191 if (phdr->p_type == PT_LOAD) {
1192 uptr seg_start = phdr->p_vaddr + delta;
1193 uptr seg_end = seg_start + phdr->p_memsz;
1194 // None of these values are aligned. We consider the ragged edges of the
1195 // load command as defined, since they are mapped from the file.
1196 seg_start = RoundDownTo(seg_start, GetPageSizeCached());
1197 seg_end = RoundUpTo(seg_end, GetPageSizeCached());
1198 cb((void *)seg_start, seg_end - seg_start);
1199 }
1200 }
1201}
1202#endif
1203
1204#if defined(__x86_64__) && SANITIZER_LINUX
1205// We cannot use glibc's clone wrapper, because it messes with the child
1206// task's TLS. It writes the PID and TID of the child task to its thread
1207// descriptor, but in our case the child task shares the thread descriptor with
1208// the parent (because we don't know how to allocate a new thread
1209// descriptor to keep glibc happy). So the stock version of clone(), when
1210// used with CLONE_VM, would end up corrupting the parent's thread descriptor.
1211uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
1212 int *parent_tidptr, void *newtls, int *child_tidptr) {
1213 long long res;
1214 if (!fn || !child_stack)
1215 return -EINVAL;
1216 CHECK_EQ(0, (uptr)child_stack % 16);
1217 child_stack = (char *)child_stack - 2 * sizeof(unsigned long long);
1218 ((unsigned long long *)child_stack)[0] = (uptr)fn;
1219 ((unsigned long long *)child_stack)[1] = (uptr)arg;
1220 register void *r8 __asm__("r8") = newtls;
1221 register int *r10 __asm__("r10") = child_tidptr;
1222 __asm__ __volatile__(
1223 /* %rax = syscall(%rax = SYSCALL(clone),
1224 * %rdi = flags,
1225 * %rsi = child_stack,
1226 * %rdx = parent_tidptr,
1227 * %r8 = new_tls,
1228 * %r10 = child_tidptr)
1229 */
1230 "syscall\n"
1231
1232 /* if (%rax != 0)
1233 * return;
1234 */
1235 "testq %%rax,%%rax\n"
1236 "jnz 1f\n"
1237
1238 /* In the child. Terminate unwind chain. */
1239 // XXX: We should also terminate the CFI unwind chain
1240 // here. Unfortunately clang 3.2 doesn't support the
1241 // necessary CFI directives, so we skip that part.
1242 "xorq %%rbp,%%rbp\n"
1243
1244 /* Call "fn(arg)". */
1245 "popq %%rax\n"
1246 "popq %%rdi\n"
1247 "call *%%rax\n"
1248
1249 /* Call _exit(%rax). */
1250 "movq %%rax,%%rdi\n"
1251 "movq %2,%%rax\n"
1252 "syscall\n"
1253
1254 /* Return to parent. */
1255 "1:\n"
1256 : "=a" (res)
1257 : "a"(SYSCALL(clone)), "i"(SYSCALL(exit)),
1258 "S"(child_stack),
1259 "D"(flags),
1260 "d"(parent_tidptr),
1261 "r"(r8),
1262 "r"(r10)
1263 : "memory", "r11", "rcx");
1264 return res;
1265}
1266#elif defined(__mips__)
1267uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
1268 int *parent_tidptr, void *newtls, int *child_tidptr) {
1269 long long res;
1270 if (!fn || !child_stack)
1271 return -EINVAL;
1272 CHECK_EQ(0, (uptr)child_stack % 16);
1273 child_stack = (char *)child_stack - 2 * sizeof(unsigned long long);
1274 ((unsigned long long *)child_stack)[0] = (uptr)fn;
1275 ((unsigned long long *)child_stack)[1] = (uptr)arg;
1276 register void *a3 __asm__("$7") = newtls;
1277 register int *a4 __asm__("$8") = child_tidptr;
1278 // We don't have proper CFI directives here because it requires alot of code
1279 // for very marginal benefits.
1280 __asm__ __volatile__(
1281 /* $v0 = syscall($v0 = __NR_clone,
1282 * $a0 = flags,
1283 * $a1 = child_stack,
1284 * $a2 = parent_tidptr,
1285 * $a3 = new_tls,
1286 * $a4 = child_tidptr)
1287 */
1288 ".cprestore 16;\n"
1289 "move $4,%1;\n"
1290 "move $5,%2;\n"
1291 "move $6,%3;\n"
1292 "move $7,%4;\n"
1293 /* Store the fifth argument on stack
1294 * if we are using 32-bit abi.
1295 */
1296#if SANITIZER_WORDSIZE == 32
1297 "lw %5,16($29);\n"
1298#else
1299 "move $8,%5;\n"
1300#endif
1301 "li $2,%6;\n"
1302 "syscall;\n"
1303
1304 /* if ($v0 != 0)
1305 * return;
1306 */
1307 "bnez $2,1f;\n"
1308
1309 /* Call "fn(arg)". */
1310#if SANITIZER_WORDSIZE == 32
1311#ifdef __BIG_ENDIAN__
1312 "lw $25,4($29);\n"
1313 "lw $4,12($29);\n"
1314#else
1315 "lw $25,0($29);\n"
1316 "lw $4,8($29);\n"
1317#endif
1318#else
1319 "ld $25,0($29);\n"
1320 "ld $4,8($29);\n"
1321#endif
1322 "jal $25;\n"
1323
1324 /* Call _exit($v0). */
1325 "move $4,$2;\n"
1326 "li $2,%7;\n"
1327 "syscall;\n"
1328
1329 /* Return to parent. */
1330 "1:\n"
1331 : "=r" (res)
1332 : "r"(flags),
1333 "r"(child_stack),
1334 "r"(parent_tidptr),
1335 "r"(a3),
1336 "r"(a4),
1337 "i"(__NR_clone),
1338 "i"(__NR_exit)
1339 : "memory", "$29" );
1340 return res;
1341}
1342#elif defined(__aarch64__)
1343uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
1344 int *parent_tidptr, void *newtls, int *child_tidptr) {
1345 long long res;
1346 if (!fn || !child_stack)
1347 return -EINVAL;
1348 CHECK_EQ(0, (uptr)child_stack % 16);
1349 child_stack = (char *)child_stack - 2 * sizeof(unsigned long long);
1350 ((unsigned long long *)child_stack)[0] = (uptr)fn;
1351 ((unsigned long long *)child_stack)[1] = (uptr)arg;
1352
1353 register int (*__fn)(void *) __asm__("x0") = fn;
1354 register void *__stack __asm__("x1") = child_stack;
1355 register int __flags __asm__("x2") = flags;
1356 register void *__arg __asm__("x3") = arg;
1357 register int *__ptid __asm__("x4") = parent_tidptr;
1358 register void *__tls __asm__("x5") = newtls;
1359 register int *__ctid __asm__("x6") = child_tidptr;
1360
1361 __asm__ __volatile__(
1362 "mov x0,x2\n" /* flags */
1363 "mov x2,x4\n" /* ptid */
1364 "mov x3,x5\n" /* tls */
1365 "mov x4,x6\n" /* ctid */
1366 "mov x8,%9\n" /* clone */
1367
1368 "svc 0x0\n"
1369
1370 /* if (%r0 != 0)
1371 * return %r0;
1372 */
1373 "cmp x0, #0\n"
1374 "bne 1f\n"
1375
1376 /* In the child, now. Call "fn(arg)". */
1377 "ldp x1, x0, [sp], #16\n"
1378 "blr x1\n"
1379
1380 /* Call _exit(%r0). */
1381 "mov x8, %10\n"
1382 "svc 0x0\n"
1383 "1:\n"
1384
1385 : "=r" (res)
1386 : "i"(-EINVAL),
1387 "r"(__fn), "r"(__stack), "r"(__flags), "r"(__arg),
1388 "r"(__ptid), "r"(__tls), "r"(__ctid),
1389 "i"(__NR_clone), "i"(__NR_exit)
1390 : "x30", "memory");
1391 return res;
1392}
1393#elif defined(__powerpc64__)
1394uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
1395 int *parent_tidptr, void *newtls, int *child_tidptr) {
1396 long long res;
1397// Stack frame structure.
1398#if SANITIZER_PPC64V1
1399// Back chain == 0 (SP + 112)
1400// Frame (112 bytes):
1401// Parameter save area (SP + 48), 8 doublewords
1402// TOC save area (SP + 40)
1403// Link editor doubleword (SP + 32)
1404// Compiler doubleword (SP + 24)
1405// LR save area (SP + 16)
1406// CR save area (SP + 8)
1407// Back chain (SP + 0)
1408# define FRAME_SIZE 112
1409# define FRAME_TOC_SAVE_OFFSET 40
1410#elif SANITIZER_PPC64V2
1411// Back chain == 0 (SP + 32)
1412// Frame (32 bytes):
1413// TOC save area (SP + 24)
1414// LR save area (SP + 16)
1415// CR save area (SP + 8)
1416// Back chain (SP + 0)
1417# define FRAME_SIZE 32
1418# define FRAME_TOC_SAVE_OFFSET 24
1419#else
1420# error "Unsupported PPC64 ABI"
1421#endif
1422 if (!fn || !child_stack)
1423 return -EINVAL;
1424 CHECK_EQ(0, (uptr)child_stack % 16);
1425
1426 register int (*__fn)(void *) __asm__("r3") = fn;
1427 register void *__cstack __asm__("r4") = child_stack;
1428 register int __flags __asm__("r5") = flags;
1429 register void *__arg __asm__("r6") = arg;
1430 register int *__ptidptr __asm__("r7") = parent_tidptr;
1431 register void *__newtls __asm__("r8") = newtls;
1432 register int *__ctidptr __asm__("r9") = child_tidptr;
1433
1434 __asm__ __volatile__(
1435 /* fn and arg are saved across the syscall */
1436 "mr 28, %5\n\t"
1437 "mr 27, %8\n\t"
1438
1439 /* syscall
1440 r0 == __NR_clone
1441 r3 == flags
1442 r4 == child_stack
1443 r5 == parent_tidptr
1444 r6 == newtls
1445 r7 == child_tidptr */
1446 "mr 3, %7\n\t"
1447 "mr 5, %9\n\t"
1448 "mr 6, %10\n\t"
1449 "mr 7, %11\n\t"
1450 "li 0, %3\n\t"
1451 "sc\n\t"
1452
1453 /* Test if syscall was successful */
1454 "cmpdi cr1, 3, 0\n\t"
1455 "crandc cr1*4+eq, cr1*4+eq, cr0*4+so\n\t"
1456 "bne- cr1, 1f\n\t"
1457
1458 /* Set up stack frame */
1459 "li 29, 0\n\t"
1460 "stdu 29, -8(1)\n\t"
1461 "stdu 1, -%12(1)\n\t"
1462 /* Do the function call */
1463 "std 2, %13(1)\n\t"
1464#if SANITIZER_PPC64V1
1465 "ld 0, 0(28)\n\t"
1466 "ld 2, 8(28)\n\t"
1467 "mtctr 0\n\t"
1468#elif SANITIZER_PPC64V2
1469 "mr 12, 28\n\t"
1470 "mtctr 12\n\t"
1471#else
1472# error "Unsupported PPC64 ABI"
1473#endif
1474 "mr 3, 27\n\t"
1475 "bctrl\n\t"
1476 "ld 2, %13(1)\n\t"
1477
1478 /* Call _exit(r3) */
1479 "li 0, %4\n\t"
1480 "sc\n\t"
1481
1482 /* Return to parent */
1483 "1:\n\t"
1484 "mr %0, 3\n\t"
1485 : "=r" (res)
1486 : "0" (-1),
1487 "i" (EINVAL),
1488 "i" (__NR_clone),
1489 "i" (__NR_exit),
1490 "r" (__fn),
1491 "r" (__cstack),
1492 "r" (__flags),
1493 "r" (__arg),
1494 "r" (__ptidptr),
1495 "r" (__newtls),
1496 "r" (__ctidptr),
1497 "i" (FRAME_SIZE),
1498 "i" (FRAME_TOC_SAVE_OFFSET)
1499 : "cr0", "cr1", "memory", "ctr", "r0", "r27", "r28", "r29");
1500 return res;
1501}
1502#elif defined(__i386__) && SANITIZER_LINUX
1503uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
1504 int *parent_tidptr, void *newtls, int *child_tidptr) {
1505 int res;
1506 if (!fn || !child_stack)
1507 return -EINVAL;
1508 CHECK_EQ(0, (uptr)child_stack % 16);
1509 child_stack = (char *)child_stack - 7 * sizeof(unsigned int);
1510 ((unsigned int *)child_stack)[0] = (uptr)flags;
1511 ((unsigned int *)child_stack)[1] = (uptr)0;
1512 ((unsigned int *)child_stack)[2] = (uptr)fn;
1513 ((unsigned int *)child_stack)[3] = (uptr)arg;
1514 __asm__ __volatile__(
1515 /* %eax = syscall(%eax = SYSCALL(clone),
1516 * %ebx = flags,
1517 * %ecx = child_stack,
1518 * %edx = parent_tidptr,
1519 * %esi = new_tls,
1520 * %edi = child_tidptr)
1521 */
1522
1523 /* Obtain flags */
1524 "movl (%%ecx), %%ebx\n"
1525 /* Do the system call */
1526 "pushl %%ebx\n"
1527 "pushl %%esi\n"
1528 "pushl %%edi\n"
1529 /* Remember the flag value. */
1530 "movl %%ebx, (%%ecx)\n"
1531 "int $0x80\n"
1532 "popl %%edi\n"
1533 "popl %%esi\n"
1534 "popl %%ebx\n"
1535
1536 /* if (%eax != 0)
1537 * return;
1538 */
1539
1540 "test %%eax,%%eax\n"
1541 "jnz 1f\n"
1542
1543 /* terminate the stack frame */
1544 "xorl %%ebp,%%ebp\n"
1545 /* Call FN. */
1546 "call *%%ebx\n"
1547#ifdef PIC
1548 "call here\n"
1549 "here:\n"
1550 "popl %%ebx\n"
1551 "addl $_GLOBAL_OFFSET_TABLE_+[.-here], %%ebx\n"
1552#endif
1553 /* Call exit */
1554 "movl %%eax, %%ebx\n"
1555 "movl %2, %%eax\n"
1556 "int $0x80\n"
1557 "1:\n"
1558 : "=a" (res)
1559 : "a"(SYSCALL(clone)), "i"(SYSCALL(exit)),
1560 "c"(child_stack),
1561 "d"(parent_tidptr),
1562 "S"(newtls),
1563 "D"(child_tidptr)
1564 : "memory");
1565 return res;
1566}
1567#elif defined(__arm__) && SANITIZER_LINUX
1568uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
1569 int *parent_tidptr, void *newtls, int *child_tidptr) {
1570 unsigned int res;
1571 if (!fn || !child_stack)
1572 return -EINVAL;
1573 child_stack = (char *)child_stack - 2 * sizeof(unsigned int);
1574 ((unsigned int *)child_stack)[0] = (uptr)fn;
1575 ((unsigned int *)child_stack)[1] = (uptr)arg;
1576 register int r0 __asm__("r0") = flags;
1577 register void *r1 __asm__("r1") = child_stack;
1578 register int *r2 __asm__("r2") = parent_tidptr;
1579 register void *r3 __asm__("r3") = newtls;
1580 register int *r4 __asm__("r4") = child_tidptr;
1581 register int r7 __asm__("r7") = __NR_clone;
1582
1583#if __ARM_ARCH > 4 || defined (__ARM_ARCH_4T__)
1584# define ARCH_HAS_BX
1585#endif
1586#if __ARM_ARCH > 4
1587# define ARCH_HAS_BLX
1588#endif
1589
1590#ifdef ARCH_HAS_BX
1591# ifdef ARCH_HAS_BLX
1592# define BLX(R) "blx " #R "\n"
1593# else
1594# define BLX(R) "mov lr, pc; bx " #R "\n"
1595# endif
1596#else
1597# define BLX(R) "mov lr, pc; mov pc," #R "\n"
1598#endif
1599
1600 __asm__ __volatile__(
1601 /* %r0 = syscall(%r7 = SYSCALL(clone),
1602 * %r0 = flags,
1603 * %r1 = child_stack,
1604 * %r2 = parent_tidptr,
1605 * %r3 = new_tls,
1606 * %r4 = child_tidptr)
1607 */
1608
1609 /* Do the system call */
1610 "swi 0x0\n"
1611
1612 /* if (%r0 != 0)
1613 * return %r0;
1614 */
1615 "cmp r0, #0\n"
1616 "bne 1f\n"
1617
1618 /* In the child, now. Call "fn(arg)". */
1619 "ldr r0, [sp, #4]\n"
1620 "ldr ip, [sp], #8\n"
1621 BLX(ip)
1622 /* Call _exit(%r0). */
1623 "mov r7, %7\n"
1624 "swi 0x0\n"
1625 "1:\n"
1626 "mov %0, r0\n"
1627 : "=r"(res)
1628 : "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r7),
1629 "i"(__NR_exit)
1630 : "memory");
1631 return res;
1632}
1633#endif // defined(__x86_64__) && SANITIZER_LINUX
1634
1635#if SANITIZER_LINUX
1636int internal_uname(struct utsname *buf) {
1637 return internal_syscall(SYSCALL(uname), buf);
1638}
1639#endif
1640
1641#if SANITIZER_ANDROID
1642#if __ANDROID_API__ < 21
1643extern "C" __attribute__((weak)) int dl_iterate_phdr(
1644 int (*)(struct dl_phdr_info *, size_t, void *), void *);
1645#endif
1646
1647static int dl_iterate_phdr_test_cb(struct dl_phdr_info *info, size_t size,
1648 void *data) {
1649 // Any name starting with "lib" indicates a bug in L where library base names
1650 // are returned instead of paths.
1651 if (info->dlpi_name && info->dlpi_name[0] == 'l' &&
1652 info->dlpi_name[1] == 'i' && info->dlpi_name[2] == 'b') {
1653 *(bool *)data = true;
1654 return 1;
1655 }
1656 return 0;
1657}
1658
1659static atomic_uint32_t android_api_level;
1660
1661static AndroidApiLevel AndroidDetectApiLevelStatic() {
1662#if __ANDROID_API__ <= 19
1663 return ANDROID_KITKAT;
1664#elif __ANDROID_API__ <= 22
1665 return ANDROID_LOLLIPOP_MR1;
1666#else
1667 return ANDROID_POST_LOLLIPOP;
1668#endif
1669}
1670
1671static AndroidApiLevel AndroidDetectApiLevel() {
1672 if (!&dl_iterate_phdr)
1673 return ANDROID_KITKAT; // K or lower
1674 bool base_name_seen = false;
1675 dl_iterate_phdr(dl_iterate_phdr_test_cb, &base_name_seen);
1676 if (base_name_seen)
1677 return ANDROID_LOLLIPOP_MR1; // L MR1
1678 return ANDROID_POST_LOLLIPOP; // post-L
1679 // Plain L (API level 21) is completely broken wrt ASan and not very
1680 // interesting to detect.
1681}
1682
1683extern "C" __attribute__((weak)) void* _DYNAMIC;
1684
1685AndroidApiLevel AndroidGetApiLevel() {
1686 AndroidApiLevel level =
1687 (AndroidApiLevel)atomic_load(&android_api_level, memory_order_relaxed);
1688 if (level) return level;
1689 level = &_DYNAMIC == nullptr ? AndroidDetectApiLevelStatic()
1690 : AndroidDetectApiLevel();
1691 atomic_store(&android_api_level, level, memory_order_relaxed);
1692 return level;
1693}
1694
1695#endif
1696
1697static HandleSignalMode GetHandleSignalModeImpl(int signum) {
1698 switch (signum) {
1699 case SIGABRT:
1700 return common_flags()->handle_abort;
1701 case SIGILL:
1702 return common_flags()->handle_sigill;
1703 case SIGTRAP:
1704 return common_flags()->handle_sigtrap;
1705 case SIGFPE:
1706 return common_flags()->handle_sigfpe;
1707 case SIGSEGV:
1708 return common_flags()->handle_segv;
1709 case SIGBUS:
1710 return common_flags()->handle_sigbus;
1711 }
1712 return kHandleSignalNo;
1713}
1714
1715HandleSignalMode GetHandleSignalMode(int signum) {
1716 HandleSignalMode result = GetHandleSignalModeImpl(signum);
1717 if (result == kHandleSignalYes && !common_flags()->allow_user_segv_handler)
1718 return kHandleSignalExclusive;
1719 return result;
1720}
1721
1722#if !SANITIZER_GO
1723void *internal_start_thread(void *(*func)(void *arg), void *arg) {
1724 // Start the thread with signals blocked, otherwise it can steal user signals.
1725 __sanitizer_sigset_t set, old;
1726 internal_sigfillset(&set);
1727#if SANITIZER_LINUX && !SANITIZER_ANDROID
1728 // Glibc uses SIGSETXID signal during setuid call. If this signal is blocked
1729 // on any thread, setuid call hangs (see test/tsan/setuid.c).
1730 internal_sigdelset(&set, 33);
1731#endif
1732 internal_sigprocmask(SIG_SETMASK, &set, &old);
1733 void *th;
1734 real_pthread_create(&th, nullptr, func, arg);
1735 internal_sigprocmask(SIG_SETMASK, &old, nullptr);
1736 return th;
1737}
1738
1739void internal_join_thread(void *th) {
1740 real_pthread_join(th, nullptr);
1741}
1742#else
1743void *internal_start_thread(void *(*func)(void *), void *arg) { return 0; }
1744
1745void internal_join_thread(void *th) {}
1746#endif
1747
1748#if defined(__aarch64__)
1749// Android headers in the older NDK releases miss this definition.
1750struct __sanitizer_esr_context {
1751 struct _aarch64_ctx head;
1752 uint64_t esr;
1753};
1754
1755static bool Aarch64GetESR(ucontext_t *ucontext, u64 *esr) {
1756 static const u32 kEsrMagic = 0x45535201;
1757 u8 *aux = ucontext->uc_mcontext.__reserved;
1758 while (true) {
1759 _aarch64_ctx *ctx = (_aarch64_ctx *)aux;
1760 if (ctx->size == 0) break;
1761 if (ctx->magic == kEsrMagic) {
1762 *esr = ((__sanitizer_esr_context *)ctx)->esr;
1763 return true;
1764 }
1765 aux += ctx->size;
1766 }
1767 return false;
1768}
1769#endif
1770
1771#if SANITIZER_OPENBSD
1772using Context = sigcontext;
1773#else
1774using Context = ucontext_t;
1775#endif
1776
1777SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
1778 Context *ucontext = (Context *)context;
1779#if defined(__x86_64__) || defined(__i386__)
1780 static const uptr PF_WRITE = 1U << 1;
1781#if SANITIZER_FREEBSD
1782 uptr err = ucontext->uc_mcontext.mc_err;
1783#elif SANITIZER_NETBSD
1784 uptr err = ucontext->uc_mcontext.__gregs[_REG_ERR];
1785#elif SANITIZER_OPENBSD
1786 uptr err = ucontext->sc_err;
1787#elif SANITIZER_SOLARIS && defined(__i386__)
1788 const int Err = 13;
1789 uptr err = ucontext->uc_mcontext.gregs[Err];
1790#else
1791 uptr err = ucontext->uc_mcontext.gregs[REG_ERR];
1792#endif // SANITIZER_FREEBSD
1793 return err & PF_WRITE ? WRITE : READ;
1794#elif defined(__mips__)
1795 uint32_t *exception_source;
1796 uint32_t faulty_instruction;
1797 uint32_t op_code;
1798
1799 exception_source = (uint32_t *)ucontext->uc_mcontext.pc;
1800 faulty_instruction = (uint32_t)(*exception_source);
1801
1802 op_code = (faulty_instruction >> 26) & 0x3f;
1803
1804 // FIXME: Add support for FPU, microMIPS, DSP, MSA memory instructions.
1805 switch (op_code) {
1806 case 0x28: // sb
1807 case 0x29: // sh
1808 case 0x2b: // sw
1809 case 0x3f: // sd
1810#if __mips_isa_rev < 6
1811 case 0x2c: // sdl
1812 case 0x2d: // sdr
1813 case 0x2a: // swl
1814 case 0x2e: // swr
1815#endif
1816 return SignalContext::WRITE;
1817
1818 case 0x20: // lb
1819 case 0x24: // lbu
1820 case 0x21: // lh
1821 case 0x25: // lhu
1822 case 0x23: // lw
1823 case 0x27: // lwu
1824 case 0x37: // ld
1825#if __mips_isa_rev < 6
1826 case 0x1a: // ldl
1827 case 0x1b: // ldr
1828 case 0x22: // lwl
1829 case 0x26: // lwr
1830#endif
1831 return SignalContext::READ;
1832#if __mips_isa_rev == 6
1833 case 0x3b: // pcrel
1834 op_code = (faulty_instruction >> 19) & 0x3;
1835 switch (op_code) {
1836 case 0x1: // lwpc
1837 case 0x2: // lwupc
1838 return SignalContext::READ;
1839 }
1840#endif
1841 }
1842 return SignalContext::UNKNOWN;
1843#elif defined(__arm__)
1844 static const uptr FSR_WRITE = 1U << 11;
1845 uptr fsr = ucontext->uc_mcontext.error_code;
1846 return fsr & FSR_WRITE ? WRITE : READ;
1847#elif defined(__aarch64__)
1848 static const u64 ESR_ELx_WNR = 1U << 6;
1849 u64 esr;
1850 if (!Aarch64GetESR(ucontext, &esr)) return UNKNOWN;
1851 return esr & ESR_ELx_WNR ? WRITE : READ;
1852#elif defined(__sparc__)
1853 // Decode the instruction to determine the access type.
1854 // From OpenSolaris $SRC/uts/sun4/os/trap.c (get_accesstype).
1855#if SANITIZER_SOLARIS
1856 uptr pc = ucontext->uc_mcontext.gregs[REG_PC];
1857#else
1858 // Historical BSDism here.
1859 struct sigcontext *scontext = (struct sigcontext *)context;
1860#if defined(__arch64__)
1861 uptr pc = scontext->sigc_regs.tpc;
1862#else
1863 uptr pc = scontext->si_regs.pc;
1864#endif
1865#endif
1866 u32 instr = *(u32 *)pc;
1867 return (instr >> 21) & 1 ? WRITE: READ;
1868#elif defined(__riscv)
1869 unsigned long pc = ucontext->uc_mcontext.__gregs[REG_PC];
1870 unsigned faulty_instruction = *(uint16_t *)pc;
1871
1872#if defined(__riscv_compressed)
1873 if ((faulty_instruction & 0x3) != 0x3) { // it's a compressed instruction
1874 // set op_bits to the instruction bits [1, 0, 15, 14, 13]
1875 unsigned op_bits =
1876 ((faulty_instruction & 0x3) << 3) | (faulty_instruction >> 13);
1877 unsigned rd = faulty_instruction & 0xF80; // bits 7-11, inclusive
1878 switch (op_bits) {
1879 case 0b10'010: // c.lwsp (rd != x0)
1880#if __riscv_xlen == 64
1881 case 0b10'011: // c.ldsp (rd != x0)
1882#endif
1883 return rd ? SignalContext::READ : SignalContext::UNKNOWN;
1884 case 0b00'010: // c.lw
1885#if __riscv_flen >= 32 && __riscv_xlen == 32
1886 case 0b10'011: // c.flwsp
1887#endif
1888#if __riscv_flen >= 32 || __riscv_xlen == 64
1889 case 0b00'011: // c.flw / c.ld
1890#endif
1891#if __riscv_flen == 64
1892 case 0b00'001: // c.fld
1893 case 0b10'001: // c.fldsp
1894#endif
1895 return SignalContext::READ;
1896 case 0b00'110: // c.sw
1897 case 0b10'110: // c.swsp
1898#if __riscv_flen >= 32 || __riscv_xlen == 64
1899 case 0b00'111: // c.fsw / c.sd
1900 case 0b10'111: // c.fswsp / c.sdsp
1901#endif
1902#if __riscv_flen == 64
1903 case 0b00'101: // c.fsd
1904 case 0b10'101: // c.fsdsp
1905#endif
1906 return SignalContext::WRITE;
1907 default:
1908 return SignalContext::UNKNOWN;
1909 }
1910 }
1911#endif
1912
1913 unsigned opcode = faulty_instruction & 0x7f; // lower 7 bits
1914 unsigned funct3 = (faulty_instruction >> 12) & 0x7; // bits 12-14, inclusive
1915 switch (opcode) {
1916 case 0b0000011: // loads
1917 switch (funct3) {
1918 case 0b000: // lb
1919 case 0b001: // lh
1920 case 0b010: // lw
1921#if __riscv_xlen == 64
1922 case 0b011: // ld
1923#endif
1924 case 0b100: // lbu
1925 case 0b101: // lhu
1926 return SignalContext::READ;
1927 default:
1928 return SignalContext::UNKNOWN;
1929 }
1930 case 0b0100011: // stores
1931 switch (funct3) {
1932 case 0b000: // sb
1933 case 0b001: // sh
1934 case 0b010: // sw
1935#if __riscv_xlen == 64
1936 case 0b011: // sd
1937#endif
1938 return SignalContext::WRITE;
1939 default:
1940 return SignalContext::UNKNOWN;
1941 }
1942#if __riscv_flen >= 32
1943 case 0b0000111: // floating-point loads
1944 switch (funct3) {
1945 case 0b010: // flw
1946#if __riscv_flen == 64
1947 case 0b011: // fld
1948#endif
1949 return SignalContext::READ;
1950 default:
1951 return SignalContext::UNKNOWN;
1952 }
1953 case 0b0100111: // floating-point stores
1954 switch (funct3) {
1955 case 0b010: // fsw
1956#if __riscv_flen == 64
1957 case 0b011: // fsd
1958#endif
1959 return SignalContext::WRITE;
1960 default:
1961 return SignalContext::UNKNOWN;
1962 }
1963#endif
1964 default:
1965 return SignalContext::UNKNOWN;
1966 }
1967#else
1968 (void)ucontext;
1969 return UNKNOWN; // FIXME: Implement.
1970#endif
1971}
1972
1973bool SignalContext::IsTrueFaultingAddress() const {
1974 auto si = static_cast<const siginfo_t *>(siginfo);
1975 // SIGSEGV signals without a true fault address have si_code set to 128.
1976 return si->si_signo == SIGSEGV && si->si_code != 128;
1977}
1978
1979void SignalContext::DumpAllRegisters(void *context) {
1980 // FIXME: Implement this.
1981}
1982
1983static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
1984#if SANITIZER_NETBSD
1985 // This covers all NetBSD architectures
1986 ucontext_t *ucontext = (ucontext_t *)context;
1987 *pc = _UC_MACHINE_PC(ucontext);
1988 *bp = _UC_MACHINE_FP(ucontext);
1989 *sp = _UC_MACHINE_SP(ucontext);
1990#elif defined(__arm__)
1991 ucontext_t *ucontext = (ucontext_t*)context;
1992 *pc = ucontext->uc_mcontext.arm_pc;
1993 *bp = ucontext->uc_mcontext.arm_fp;
1994 *sp = ucontext->uc_mcontext.arm_sp;
1995#elif defined(__aarch64__)
1996 ucontext_t *ucontext = (ucontext_t*)context;
1997 *pc = ucontext->uc_mcontext.pc;
1998 *bp = ucontext->uc_mcontext.regs[29];
1999 *sp = ucontext->uc_mcontext.sp;
2000#elif defined(__hppa__)
2001 ucontext_t *ucontext = (ucontext_t*)context;
2002 *pc = ucontext->uc_mcontext.sc_iaoq[0];
2003 /* GCC uses %r3 whenever a frame pointer is needed. */
2004 *bp = ucontext->uc_mcontext.sc_gr[3];
2005 *sp = ucontext->uc_mcontext.sc_gr[30];
2006#elif defined(__x86_64__)
2007# if SANITIZER_FREEBSD
2008 ucontext_t *ucontext = (ucontext_t*)context;
2009 *pc = ucontext->uc_mcontext.mc_rip;
2010 *bp = ucontext->uc_mcontext.mc_rbp;
2011 *sp = ucontext->uc_mcontext.mc_rsp;
2012#elif SANITIZER_OPENBSD
2013 sigcontext *ucontext = (sigcontext *)context;
2014 *pc = ucontext->sc_rip;
2015 *bp = ucontext->sc_rbp;
2016 *sp = ucontext->sc_rsp;
2017# else
2018 ucontext_t *ucontext = (ucontext_t*)context;
2019 *pc = ucontext->uc_mcontext.gregs[REG_RIP];
2020 *bp = ucontext->uc_mcontext.gregs[REG_RBP];
2021 *sp = ucontext->uc_mcontext.gregs[REG_RSP];
2022# endif
2023#elif defined(__i386__)
2024# if SANITIZER_FREEBSD
2025 ucontext_t *ucontext = (ucontext_t*)context;
2026 *pc = ucontext->uc_mcontext.mc_eip;
2027 *bp = ucontext->uc_mcontext.mc_ebp;
2028 *sp = ucontext->uc_mcontext.mc_esp;
2029#elif SANITIZER_OPENBSD
2030 sigcontext *ucontext = (sigcontext *)context;
2031 *pc = ucontext->sc_eip;
2032 *bp = ucontext->sc_ebp;
2033 *sp = ucontext->sc_esp;
2034# else
2035 ucontext_t *ucontext = (ucontext_t*)context;
2036# if SANITIZER_SOLARIS
2037 /* Use the numeric values: the symbolic ones are undefined by llvm
2038 include/llvm/Support/Solaris.h. */
2039# ifndef REG_EIP
2040# define REG_EIP 14 // REG_PC
2041# endif
2042# ifndef REG_EBP
2043# define REG_EBP 6 // REG_FP
2044# endif
2045# ifndef REG_UESP
2046# define REG_UESP 17 // REG_SP
2047# endif
2048# endif
2049 *pc = ucontext->uc_mcontext.gregs[REG_EIP];
2050 *bp = ucontext->uc_mcontext.gregs[REG_EBP];
2051 *sp = ucontext->uc_mcontext.gregs[REG_UESP];
2052# endif
2053#elif defined(__powerpc__) || defined(__powerpc64__)
2054 ucontext_t *ucontext = (ucontext_t*)context;
2055 *pc = ucontext->uc_mcontext.regs->nip;
2056 *sp = ucontext->uc_mcontext.regs->gpr[PT_R1];
2057 // The powerpc{,64}-linux ABIs do not specify r31 as the frame
2058 // pointer, but GCC always uses r31 when we need a frame pointer.
2059 *bp = ucontext->uc_mcontext.regs->gpr[PT_R31];
2060#elif defined(__sparc__)
2061#if defined(__arch64__) || defined(__sparcv9)
2062#define STACK_BIAS 2047
2063#else
2064#define STACK_BIAS 0
2065# endif
2066# if SANITIZER_SOLARIS
2067 ucontext_t *ucontext = (ucontext_t *)context;
2068 *pc = ucontext->uc_mcontext.gregs[REG_PC];
2069 *sp = ucontext->uc_mcontext.gregs[REG_O6] + STACK_BIAS;
2070#else
2071 // Historical BSDism here.
2072 struct sigcontext *scontext = (struct sigcontext *)context;
2073#if defined(__arch64__)
2074 *pc = scontext->sigc_regs.tpc;
2075 *sp = scontext->sigc_regs.u_regs[14] + STACK_BIAS;
2076#else
2077 *pc = scontext->si_regs.pc;
2078 *sp = scontext->si_regs.u_regs[14];
2079#endif
2080# endif
2081 *bp = (uptr)((uhwptr *)*sp)[14] + STACK_BIAS;
2082#elif defined(__mips__)
2083 ucontext_t *ucontext = (ucontext_t*)context;
2084 *pc = ucontext->uc_mcontext.pc;
2085 *bp = ucontext->uc_mcontext.gregs[30];
2086 *sp = ucontext->uc_mcontext.gregs[29];
2087#elif defined(__s390__)
2088 ucontext_t *ucontext = (ucontext_t*)context;
2089# if defined(__s390x__)
2090 *pc = ucontext->uc_mcontext.psw.addr;
2091# else
2092 *pc = ucontext->uc_mcontext.psw.addr & 0x7fffffff;
2093# endif
2094 *bp = ucontext->uc_mcontext.gregs[11];
2095 *sp = ucontext->uc_mcontext.gregs[15];
2096#elif defined(__riscv)
2097 ucontext_t *ucontext = (ucontext_t*)context;
2098 *pc = ucontext->uc_mcontext.__gregs[REG_PC];
2099 *bp = ucontext->uc_mcontext.__gregs[REG_S0];
2100 *sp = ucontext->uc_mcontext.__gregs[REG_SP];
2101#else
2102# error "Unsupported arch"
2103#endif
2104}
2105
2106void SignalContext::InitPcSpBp() { GetPcSpBp(context, &pc, &sp, &bp); }
2107
2108void InitializePlatformEarly() {
2109 // Do nothing.
2110}
2111
2112void MaybeReexec() {
2113 // No need to re-exec on Linux.
2114}
2115
2116void CheckASLR() {
2117#if SANITIZER_NETBSD
2118 int mib[3];
2119 int paxflags;
2120 uptr len = sizeof(paxflags);
2121
2122 mib[0] = CTL_PROC;
2123 mib[1] = internal_getpid();
2124 mib[2] = PROC_PID_PAXFLAGS;
2125
2126 if (UNLIKELY(internal_sysctl(mib, 3, &paxflags, &len, NULL, 0) == -1)) {
2127 Printf("sysctl failed\n");
2128 Die();
2129 }
2130
2131 if (UNLIKELY(paxflags & CTL_PROC_PAXFLAGS_ASLR)) {
2132 Printf("This sanitizer is not compatible with enabled ASLR.\n"
2133 "To disable ASLR, please run \"paxctl +a %s\" and try again.\n",
2134 GetArgv()[0]);
2135 Die();
2136 }
2137#elif SANITIZER_PPC64V2
2138 // Disable ASLR for Linux PPC64LE.
2139 int old_personality = personality(0xffffffff);
2140 if (old_personality != -1 && (old_personality & ADDR_NO_RANDOMIZE) == 0) {
2141 VReport(1, "WARNING: Program is being run with address space layout "
2142 "randomization (ASLR) enabled which prevents the thread and "
2143 "memory sanitizers from working on powerpc64le.\n"
2144 "ASLR will be disabled and the program re-executed.\n");
2145 CHECK_NE(personality(old_personality | ADDR_NO_RANDOMIZE), -1);
2146 ReExec();
2147 }
2148#elif SANITIZER_FREEBSD
2149 int aslr_pie;
2150 uptr len = sizeof(aslr_pie);
2151#if SANITIZER_WORDSIZE == 64
2152 if (UNLIKELY(internal_sysctlbyname("kern.elf64.aslr.pie_enable",
2153 &aslr_pie, &len, NULL, 0) == -1)) {
2154 // We're making things less 'dramatic' here since
2155 // the OID is not necessarily guaranteed to be here
2156 // just yet regarding FreeBSD release
2157 return;
2158 }
2159
2160 if (aslr_pie > 0) {
2161 Printf("This sanitizer is not compatible with enabled ASLR "
2162 "and binaries compiled with PIE\n");
2163 Die();
2164 }
2165#endif
2166 // there might be 32 bits compat for 64 bits
2167 if (UNLIKELY(internal_sysctlbyname("kern.elf32.aslr.pie_enable",
2168 &aslr_pie, &len, NULL, 0) == -1)) {
2169 return;
2170 }
2171
2172 if (aslr_pie > 0) {
2173 Printf("This sanitizer is not compatible with enabled ASLR "
2174 "and binaries compiled with PIE\n");
2175 Die();
2176 }
2177#else
2178 // Do nothing
2179#endif
2180}
2181
2182void CheckMPROTECT() {
2183#if SANITIZER_NETBSD
2184 int mib[3];
2185 int paxflags;
2186 uptr len = sizeof(paxflags);
2187
2188 mib[0] = CTL_PROC;
2189 mib[1] = internal_getpid();
2190 mib[2] = PROC_PID_PAXFLAGS;
2191
2192 if (UNLIKELY(internal_sysctl(mib, 3, &paxflags, &len, NULL, 0) == -1)) {
2193 Printf("sysctl failed\n");
2194 Die();
2195 }
2196
2197 if (UNLIKELY(paxflags & CTL_PROC_PAXFLAGS_MPROTECT)) {
2198 Printf("This sanitizer is not compatible with enabled MPROTECT\n");
2199 Die();
2200 }
2201#else
2202 // Do nothing
2203#endif
2204}
2205
2206void PrintModuleMap() { }
2207
2208void CheckNoDeepBind(const char *filename, int flag) {
2209#ifdef RTLD_DEEPBIND
2210 if (flag & RTLD_DEEPBIND) {
2211 Report(
2212 "You are trying to dlopen a %s shared library with RTLD_DEEPBIND flag"
2213 " which is incompatible with sanitizer runtime "
2214 "(see https://github.com/google/sanitizers/issues/611 for details"
2215 "). If you want to run %s library under sanitizers please remove "
2216 "RTLD_DEEPBIND from dlopen flags.\n",
2217 filename, filename);
2218 Die();
2219 }
2220#endif
2221}
2222
2223uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,
2224 uptr *largest_gap_found,
2225 uptr *max_occupied_addr) {
2226 UNREACHABLE("FindAvailableMemoryRange is not available");
2227 return 0;
2228}
2229
2230bool GetRandom(void *buffer, uptr length, bool blocking) {
2231 if (!buffer || !length || length > 256)
2232 return false;
2233#if SANITIZER_USE_GETENTROPY
2234 uptr rnd = getentropy(buffer, length);
2235 int rverrno = 0;
2236 if (internal_iserror(rnd, &rverrno) && rverrno == EFAULT)
2237 return false;
2238 else if (rnd == 0)
2239 return true;
2240#endif // SANITIZER_USE_GETENTROPY
2241
2242#if SANITIZER_USE_GETRANDOM
2243 static atomic_uint8_t skip_getrandom_syscall;
2244 if (!atomic_load_relaxed(&skip_getrandom_syscall)) {
2245 // Up to 256 bytes, getrandom will not be interrupted.
2246 uptr res = internal_syscall(SYSCALL(getrandom), buffer, length,
2247 blocking ? 0 : GRND_NONBLOCK);
2248 int rverrno = 0;
2249 if (internal_iserror(res, &rverrno) && rverrno == ENOSYS)
2250 atomic_store_relaxed(&skip_getrandom_syscall, 1);
2251 else if (res == length)
2252 return true;
2253 }
2254#endif // SANITIZER_USE_GETRANDOM
2255 // Up to 256 bytes, a read off /dev/urandom will not be interrupted.
2256 // blocking is moot here, O_NONBLOCK has no effect when opening /dev/urandom.
2257 uptr fd = internal_open("/dev/urandom", O_RDONLY);
2258 if (internal_iserror(fd))
2259 return false;
2260 uptr res = internal_read(fd, buffer, length);
2261 if (internal_iserror(res))
2262 return false;
2263 internal_close(fd);
2264 return true;
2265}
2266
2267} // namespace __sanitizer
2268
2269#endif
lib/tsan/sanitizer_common/sanitizer_linux.h created+162
...@@ -0,0 +1,162 @@
1//===-- sanitizer_linux.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// Linux-specific syscall wrappers and classes.
10//
11//===----------------------------------------------------------------------===//
12#ifndef SANITIZER_LINUX_H
13#define SANITIZER_LINUX_H
14
15#include "sanitizer_platform.h"
16#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
17 SANITIZER_OPENBSD || SANITIZER_SOLARIS
18#include "sanitizer_common.h"
19#include "sanitizer_internal_defs.h"
20#include "sanitizer_platform_limits_freebsd.h"
21#include "sanitizer_platform_limits_netbsd.h"
22#include "sanitizer_platform_limits_openbsd.h"
23#include "sanitizer_platform_limits_posix.h"
24#include "sanitizer_platform_limits_solaris.h"
25#include "sanitizer_posix.h"
26
27struct link_map; // Opaque type returned by dlopen().
28struct utsname;
29
30namespace __sanitizer {
31// Dirent structure for getdents(). Note that this structure is different from
32// the one in <dirent.h>, which is used by readdir().
33struct linux_dirent;
34
35struct ProcSelfMapsBuff {
36 char *data;
37 uptr mmaped_size;
38 uptr len;
39};
40
41struct MemoryMappingLayoutData {
42 ProcSelfMapsBuff proc_self_maps;
43 const char *current;
44};
45
46void ReadProcMaps(ProcSelfMapsBuff *proc_maps);
47
48// Syscall wrappers.
49uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count);
50uptr internal_sigaltstack(const void* ss, void* oss);
51uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set,
52 __sanitizer_sigset_t *oldset);
53uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp);
54
55// Linux-only syscalls.
56#if SANITIZER_LINUX
57uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5);
58// Used only by sanitizer_stoptheworld. Signal handlers that are actually used
59// (like the process-wide error reporting SEGV handler) must use
60// internal_sigaction instead.
61int internal_sigaction_norestorer(int signum, const void *act, void *oldact);
62void internal_sigdelset(__sanitizer_sigset_t *set, int signum);
63#if defined(__x86_64__) || defined(__mips__) || defined(__aarch64__) \
64 || defined(__powerpc64__) || defined(__s390__) || defined(__i386__) \
65 || defined(__arm__)
66uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
67 int *parent_tidptr, void *newtls, int *child_tidptr);
68#endif
69int internal_uname(struct utsname *buf);
70#elif SANITIZER_FREEBSD
71void internal_sigdelset(__sanitizer_sigset_t *set, int signum);
72#elif SANITIZER_NETBSD
73void internal_sigdelset(__sanitizer_sigset_t *set, int signum);
74uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg);
75#endif // SANITIZER_LINUX
76
77// This class reads thread IDs from /proc/<pid>/task using only syscalls.
78class ThreadLister {
79 public:
80 explicit ThreadLister(pid_t pid);
81 ~ThreadLister();
82 enum Result {
83 Error,
84 Incomplete,
85 Ok,
86 };
87 Result ListThreads(InternalMmapVector<tid_t> *threads);
88
89 private:
90 bool IsAlive(int tid);
91
92 pid_t pid_;
93 int descriptor_ = -1;
94 InternalMmapVector<char> buffer_;
95};
96
97// Exposed for testing.
98uptr ThreadDescriptorSize();
99uptr ThreadSelf();
100uptr ThreadSelfOffset();
101
102// Matches a library's file name against a base name (stripping path and version
103// information).
104bool LibraryNameIs(const char *full_name, const char *base_name);
105
106// Call cb for each region mapped by map.
107void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr));
108
109// Releases memory pages entirely within the [beg, end] address range.
110// The pages no longer count toward RSS; reads are guaranteed to return 0.
111// Requires (but does not verify!) that pages are MAP_PRIVATE.
112INLINE void ReleaseMemoryPagesToOSAndZeroFill(uptr beg, uptr end) {
113 // man madvise on Linux promises zero-fill for anonymous private pages.
114 // Testing shows the same behaviour for private (but not anonymous) mappings
115 // of shm_open() files, as long as the underlying file is untouched.
116 CHECK(SANITIZER_LINUX);
117 ReleaseMemoryPagesToOS(beg, end);
118}
119
120#if SANITIZER_ANDROID
121
122#if defined(__aarch64__)
123# define __get_tls() \
124 ({ void** __v; __asm__("mrs %0, tpidr_el0" : "=r"(__v)); __v; })
125#elif defined(__arm__)
126# define __get_tls() \
127 ({ void** __v; __asm__("mrc p15, 0, %0, c13, c0, 3" : "=r"(__v)); __v; })
128#elif defined(__mips__)
129// On mips32r1, this goes via a kernel illegal instruction trap that's
130// optimized for v1.
131# define __get_tls() \
132 ({ register void** __v asm("v1"); \
133 __asm__(".set push\n" \
134 ".set mips32r2\n" \
135 "rdhwr %0,$29\n" \
136 ".set pop\n" : "=r"(__v)); \
137 __v; })
138#elif defined(__i386__)
139# define __get_tls() \
140 ({ void** __v; __asm__("movl %%gs:0, %0" : "=r"(__v)); __v; })
141#elif defined(__x86_64__)
142# define __get_tls() \
143 ({ void** __v; __asm__("mov %%fs:0, %0" : "=r"(__v)); __v; })
144#else
145#error "Unsupported architecture."
146#endif
147
148// The Android Bionic team has allocated a TLS slot for sanitizers starting
149// with Q, given that Android currently doesn't support ELF TLS. It is used to
150// store sanitizer thread specific data.
151static const int TLS_SLOT_SANITIZER = 6;
152
153ALWAYS_INLINE uptr *get_android_tls_ptr() {
154 return reinterpret_cast<uptr *>(&__get_tls()[TLS_SLOT_SANITIZER]);
155}
156
157#endif // SANITIZER_ANDROID
158
159} // namespace __sanitizer
160
161#endif
162#endif // SANITIZER_LINUX_H
lib/tsan/sanitizer_common/sanitizer_linux_s390.cpp created+222
...@@ -0,0 +1,222 @@
1//===-- sanitizer_linux_s390.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 shared between AddressSanitizer and ThreadSanitizer
10// run-time libraries and implements s390-linux-specific functions from
11// sanitizer_libc.h.
12//===----------------------------------------------------------------------===//
13
14#include "sanitizer_platform.h"
15
16#if SANITIZER_LINUX && SANITIZER_S390
17
18#include <dlfcn.h>
19#include <errno.h>
20#include <sys/syscall.h>
21#include <sys/utsname.h>
22#include <unistd.h>
23
24#include "sanitizer_libc.h"
25#include "sanitizer_linux.h"
26
27namespace __sanitizer {
28
29// --------------- sanitizer_libc.h
30uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd,
31 u64 offset) {
32 struct s390_mmap_params {
33 unsigned long addr;
34 unsigned long length;
35 unsigned long prot;
36 unsigned long flags;
37 unsigned long fd;
38 unsigned long offset;
39 } params = {
40 (unsigned long)addr,
41 (unsigned long)length,
42 (unsigned long)prot,
43 (unsigned long)flags,
44 (unsigned long)fd,
45# ifdef __s390x__
46 (unsigned long)offset,
47# else
48 (unsigned long)(offset / 4096),
49# endif
50 };
51# ifdef __s390x__
52 return syscall(__NR_mmap, &params);
53# else
54 return syscall(__NR_mmap2, &params);
55# endif
56}
57
58uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
59 int *parent_tidptr, void *newtls, int *child_tidptr) {
60 if (!fn || !child_stack)
61 return -EINVAL;
62 CHECK_EQ(0, (uptr)child_stack % 16);
63 // Minimum frame size.
64#ifdef __s390x__
65 child_stack = (char *)child_stack - 160;
66#else
67 child_stack = (char *)child_stack - 96;
68#endif
69 // Terminate unwind chain.
70 ((unsigned long *)child_stack)[0] = 0;
71 // And pass parameters.
72 ((unsigned long *)child_stack)[1] = (uptr)fn;
73 ((unsigned long *)child_stack)[2] = (uptr)arg;
74 register long res __asm__("r2");
75 register void *__cstack __asm__("r2") = child_stack;
76 register int __flags __asm__("r3") = flags;
77 register int * __ptidptr __asm__("r4") = parent_tidptr;
78 register int * __ctidptr __asm__("r5") = child_tidptr;
79 register void * __newtls __asm__("r6") = newtls;
80
81 __asm__ __volatile__(
82 /* Clone. */
83 "svc %1\n"
84
85 /* if (%r2 != 0)
86 * return;
87 */
88#ifdef __s390x__
89 "cghi %%r2, 0\n"
90#else
91 "chi %%r2, 0\n"
92#endif
93 "jne 1f\n"
94
95 /* Call "fn(arg)". */
96#ifdef __s390x__
97 "lmg %%r1, %%r2, 8(%%r15)\n"
98#else
99 "lm %%r1, %%r2, 4(%%r15)\n"
100#endif
101 "basr %%r14, %%r1\n"
102
103 /* Call _exit(%r2). */
104 "svc %2\n"
105
106 /* Return to parent. */
107 "1:\n"
108 : "=r" (res)
109 : "i"(__NR_clone), "i"(__NR_exit),
110 "r"(__cstack),
111 "r"(__flags),
112 "r"(__ptidptr),
113 "r"(__ctidptr),
114 "r"(__newtls)
115 : "memory", "cc");
116 return res;
117}
118
119#if SANITIZER_S390_64
120static bool FixedCVE_2016_2143() {
121 // Try to determine if the running kernel has a fix for CVE-2016-2143,
122 // return false if in doubt (better safe than sorry). Distros may want to
123 // adjust this for their own kernels.
124 struct utsname buf;
125 unsigned int major, minor, patch = 0;
126 // This should never fail, but just in case...
127 if (internal_uname(&buf))
128 return false;
129 const char *ptr = buf.release;
130 major = internal_simple_strtoll(ptr, &ptr, 10);
131 // At least first 2 should be matched.
132 if (ptr[0] != '.')
133 return false;
134 minor = internal_simple_strtoll(ptr+1, &ptr, 10);
135 // Third is optional.
136 if (ptr[0] == '.')
137 patch = internal_simple_strtoll(ptr+1, &ptr, 10);
138 if (major < 3) {
139 if (major == 2 && minor == 6 && patch == 32 && ptr[0] == '-' &&
140 internal_strstr(ptr, ".el6")) {
141 // Check RHEL6
142 int r1 = internal_simple_strtoll(ptr+1, &ptr, 10);
143 if (r1 >= 657) // 2.6.32-657.el6 or later
144 return true;
145 if (r1 == 642 && ptr[0] == '.') {
146 int r2 = internal_simple_strtoll(ptr+1, &ptr, 10);
147 if (r2 >= 9) // 2.6.32-642.9.1.el6 or later
148 return true;
149 }
150 }
151 // <3.0 is bad.
152 return false;
153 } else if (major == 3) {
154 // 3.2.79+ is OK.
155 if (minor == 2 && patch >= 79)
156 return true;
157 // 3.12.58+ is OK.
158 if (minor == 12 && patch >= 58)
159 return true;
160 if (minor == 10 && patch == 0 && ptr[0] == '-' &&
161 internal_strstr(ptr, ".el7")) {
162 // Check RHEL7
163 int r1 = internal_simple_strtoll(ptr+1, &ptr, 10);
164 if (r1 >= 426) // 3.10.0-426.el7 or later
165 return true;
166 if (r1 == 327 && ptr[0] == '.') {
167 int r2 = internal_simple_strtoll(ptr+1, &ptr, 10);
168 if (r2 >= 27) // 3.10.0-327.27.1.el7 or later
169 return true;
170 }
171 }
172 // Otherwise, bad.
173 return false;
174 } else if (major == 4) {
175 // 4.1.21+ is OK.
176 if (minor == 1 && patch >= 21)
177 return true;
178 // 4.4.6+ is OK.
179 if (minor == 4 && patch >= 6)
180 return true;
181 if (minor == 4 && patch == 0 && ptr[0] == '-' &&
182 internal_strstr(buf.version, "Ubuntu")) {
183 // Check Ubuntu 16.04
184 int r1 = internal_simple_strtoll(ptr+1, &ptr, 10);
185 if (r1 >= 13) // 4.4.0-13 or later
186 return true;
187 }
188 // Otherwise, OK if 4.5+.
189 return minor >= 5;
190 } else {
191 // Linux 5 and up are fine.
192 return true;
193 }
194}
195
196void AvoidCVE_2016_2143() {
197 // Older kernels are affected by CVE-2016-2143 - they will crash hard
198 // if someone uses 4-level page tables (ie. virtual addresses >= 4TB)
199 // and fork() in the same process. Unfortunately, sanitizers tend to
200 // require such addresses. Since this is very likely to crash the whole
201 // machine (sanitizers themselves use fork() for llvm-symbolizer, for one),
202 // abort the process at initialization instead.
203 if (FixedCVE_2016_2143())
204 return;
205 if (GetEnv("SANITIZER_IGNORE_CVE_2016_2143"))
206 return;
207 Report(
208 "ERROR: Your kernel seems to be vulnerable to CVE-2016-2143. Using ASan,\n"
209 "MSan, TSan, DFSan or LSan with such kernel can and will crash your\n"
210 "machine, or worse.\n"
211 "\n"
212 "If you are certain your kernel is not vulnerable (you have compiled it\n"
213 "yourself, or are using an unrecognized distribution kernel), you can\n"
214 "override this safety check by exporting SANITIZER_IGNORE_CVE_2016_2143\n"
215 "with any value.\n");
216 Die();
217}
218#endif
219
220} // namespace __sanitizer
221
222#endif // SANITIZER_LINUX && SANITIZER_S390
lib/tsan/sanitizer_common/sanitizer_list.h created+166
...@@ -0,0 +1,166 @@
1//===-- sanitizer_list.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 contains implementation of a list class to be used by
10// ThreadSanitizer, etc run-times.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef SANITIZER_LIST_H
15#define SANITIZER_LIST_H
16
17#include "sanitizer_internal_defs.h"
18
19namespace __sanitizer {
20
21// Intrusive singly-linked list with size(), push_back(), push_front()
22// pop_front(), append_front() and append_back().
23// This class should be a POD (so that it can be put into TLS)
24// and an object with all zero fields should represent a valid empty list.
25// This class does not have a CTOR, so clear() should be called on all
26// non-zero-initialized objects before using.
27template<class Item>
28struct IntrusiveList {
29 friend class Iterator;
30
31 void clear() {
32 first_ = last_ = nullptr;
33 size_ = 0;
34 }
35
36 bool empty() const { return size_ == 0; }
37 uptr size() const { return size_; }
38
39 void push_back(Item *x) {
40 if (empty()) {
41 x->next = nullptr;
42 first_ = last_ = x;
43 size_ = 1;
44 } else {
45 x->next = nullptr;
46 last_->next = x;
47 last_ = x;
48 size_++;
49 }
50 }
51
52 void push_front(Item *x) {
53 if (empty()) {
54 x->next = nullptr;
55 first_ = last_ = x;
56 size_ = 1;
57 } else {
58 x->next = first_;
59 first_ = x;
60 size_++;
61 }
62 }
63
64 void pop_front() {
65 CHECK(!empty());
66 first_ = first_->next;
67 if (!first_)
68 last_ = nullptr;
69 size_--;
70 }
71
72 void extract(Item *prev, Item *x) {
73 CHECK(!empty());
74 CHECK_NE(prev, nullptr);
75 CHECK_NE(x, nullptr);
76 CHECK_EQ(prev->next, x);
77 prev->next = x->next;
78 if (last_ == x)
79 last_ = prev;
80 size_--;
81 }
82
83 Item *front() { return first_; }
84 const Item *front() const { return first_; }
85 Item *back() { return last_; }
86 const Item *back() const { return last_; }
87
88 void append_front(IntrusiveList<Item> *l) {
89 CHECK_NE(this, l);
90 if (l->empty())
91 return;
92 if (empty()) {
93 *this = *l;
94 } else if (!l->empty()) {
95 l->last_->next = first_;
96 first_ = l->first_;
97 size_ += l->size();
98 }
99 l->clear();
100 }
101
102 void append_back(IntrusiveList<Item> *l) {
103 CHECK_NE(this, l);
104 if (l->empty())
105 return;
106 if (empty()) {
107 *this = *l;
108 } else {
109 last_->next = l->first_;
110 last_ = l->last_;
111 size_ += l->size();
112 }
113 l->clear();
114 }
115
116 void CheckConsistency() {
117 if (size_ == 0) {
118 CHECK_EQ(first_, 0);
119 CHECK_EQ(last_, 0);
120 } else {
121 uptr count = 0;
122 for (Item *i = first_; ; i = i->next) {
123 count++;
124 if (i == last_) break;
125 }
126 CHECK_EQ(size(), count);
127 CHECK_EQ(last_->next, 0);
128 }
129 }
130
131 template<class ItemTy>
132 class IteratorBase {
133 public:
134 explicit IteratorBase(ItemTy *current) : current_(current) {}
135 IteratorBase &operator++() {
136 current_ = current_->next;
137 return *this;
138 }
139 bool operator!=(IteratorBase other) const {
140 return current_ != other.current_;
141 }
142 ItemTy &operator*() {
143 return *current_;
144 }
145 private:
146 ItemTy *current_;
147 };
148
149 typedef IteratorBase<Item> Iterator;
150 typedef IteratorBase<const Item> ConstIterator;
151
152 Iterator begin() { return Iterator(first_); }
153 Iterator end() { return Iterator(0); }
154
155 ConstIterator begin() const { return ConstIterator(first_); }
156 ConstIterator end() const { return ConstIterator(0); }
157
158// private, don't use directly.
159 uptr size_;
160 Item *first_;
161 Item *last_;
162};
163
164} // namespace __sanitizer
165
166#endif // SANITIZER_LIST_H
lib/tsan/sanitizer_common/sanitizer_local_address_space_view.h created+76
...@@ -0,0 +1,76 @@
1//===-- sanitizer_local_address_space_view.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// `LocalAddressSpaceView` provides the local (i.e. target and current address
10// space are the same) implementation of the `AddressSpaveView` interface which
11// provides a simple interface to load memory from another process (i.e.
12// out-of-process)
13//
14// The `AddressSpaceView` interface requires that the type can be used as a
15// template parameter to objects that wish to be able to operate in an
16// out-of-process manner. In normal usage, objects are in-process and are thus
17// instantiated with the `LocalAddressSpaceView` type. This type is used to
18// load any pointers in instance methods. This implementation is effectively
19// a no-op. When an object is to be used in an out-of-process manner it is
20// instansiated with the `RemoteAddressSpaceView` type.
21//
22// By making `AddressSpaceView` a template parameter of an object, it can
23// change its implementation at compile time which has no run time overhead.
24// This also allows unifying in-process and out-of-process code which avoids
25// code duplication.
26//
27//===----------------------------------------------------------------------===//
28#ifndef SANITIZER_LOCAL_ADDRES_SPACE_VIEW_H
29#define SANITIZER_LOCAL_ADDRES_SPACE_VIEW_H
30
31namespace __sanitizer {
32struct LocalAddressSpaceView {
33 // Load memory `sizeof(T) * num_elements` bytes of memory from the target
34 // process (always local for this implementation) starting at address
35 // `target_address`. The local copy of this memory is returned as a pointer.
36 // The caller should not write to this memory. The behaviour when doing so is
37 // undefined. Callers should use `LoadWritable()` to get access to memory
38 // that is writable.
39 //
40 // The lifetime of loaded memory is implementation defined.
41 template <typename T>
42 static const T *Load(const T *target_address, uptr num_elements = 1) {
43 // The target address space is the local address space so
44 // nothing needs to be copied. Just return the pointer.
45 return target_address;
46 }
47
48 // Load memory `sizeof(T) * num_elements` bytes of memory from the target
49 // process (always local for this implementation) starting at address
50 // `target_address`. The local copy of this memory is returned as a pointer.
51 // The memory returned may be written to.
52 //
53 // Writes made to the returned memory will be visible in the memory returned
54 // by subsequent `Load()` or `LoadWritable()` calls provided the
55 // `target_address` parameter is the same. It is not guaranteed that the
56 // memory returned by previous calls to `Load()` will contain any performed
57 // writes. If two or more overlapping regions of memory are loaded via
58 // separate calls to `LoadWritable()`, it is implementation defined whether
59 // writes made to the region returned by one call are visible in the regions
60 // returned by other calls.
61 //
62 // Given the above it is recommended to load the largest possible object
63 // that requires modification (e.g. a class) rather than individual fields
64 // from a class to avoid issues with overlapping writable regions.
65 //
66 // The lifetime of loaded memory is implementation defined.
67 template <typename T>
68 static T *LoadWritable(T *target_address, uptr num_elements = 1) {
69 // The target address space is the local address space so
70 // nothing needs to be copied. Just return the pointer.
71 return target_address;
72 }
73};
74} // namespace __sanitizer
75
76#endif
lib/tsan/sanitizer_common/sanitizer_mac.cpp created+1228
...@@ -0,0 +1,1228 @@
1//===-- sanitizer_mac.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 shared between various sanitizers' runtime libraries and
10// implements OSX-specific functions.
11//===----------------------------------------------------------------------===//
12
13#include "sanitizer_platform.h"
14#if SANITIZER_MAC
15#include "sanitizer_mac.h"
16#include "interception/interception.h"
17
18// Use 64-bit inodes in file operations. ASan does not support OS X 10.5, so
19// 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
37extern char **environ;
38#endif
39
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
46
47#if !SANITIZER_IOS
48#include <crt_externs.h> // for _NSGetArgv and _NSGetEnviron
49#else
50extern "C" {
51 extern char ***_NSGetArgv(void);
52}
53#endif
54
55#include <asl.h>
56#include <dlfcn.h> // for dladdr()
57#include <errno.h>
58#include <fcntl.h>
59#include <libkern/OSAtomic.h>
60#include <mach-o/dyld.h>
61#include <mach/mach.h>
62#include <mach/mach_time.h>
63#include <mach/vm_statistics.h>
64#include <malloc/malloc.h>
65#include <pthread.h>
66#include <sched.h>
67#include <signal.h>
68#include <spawn.h>
69#include <stdlib.h>
70#include <sys/ioctl.h>
71#include <sys/mman.h>
72#include <sys/resource.h>
73#include <sys/stat.h>
74#include <sys/sysctl.h>
75#include <sys/types.h>
76#include <sys/wait.h>
77#include <unistd.h>
78#include <util.h>
79
80// From <crt_externs.h>, but we don't have that file on iOS.
81extern "C" {
82 extern char ***_NSGetArgv(void);
83 extern char ***_NSGetEnviron(void);
84}
85
86// From <mach/mach_vm.h>, but we don't have that file on iOS.
87extern "C" {
88 extern kern_return_t mach_vm_region_recurse(
89 vm_map_t target_task,
90 mach_vm_address_t *address,
91 mach_vm_size_t *size,
92 natural_t *nesting_depth,
93 vm_region_recurse_info_t info,
94 mach_msg_type_number_t *infoCnt);
95}
96
97namespace __sanitizer {
98
99#include "sanitizer_syscall_generic.inc"
100
101// Direct syscalls, don't call libmalloc hooks (but not available on 10.6).
102extern "C" void *__mmap(void *addr, size_t len, int prot, int flags, int fildes,
103 off_t off) SANITIZER_WEAK_ATTRIBUTE;
104extern "C" int __munmap(void *, size_t) SANITIZER_WEAK_ATTRIBUTE;
105
106// ---------------------- sanitizer_libc.h
107
108// From <mach/vm_statistics.h>, but not on older OSs.
109#ifndef VM_MEMORY_SANITIZER
110#define VM_MEMORY_SANITIZER 99
111#endif
112
113// XNU on Darwin provides a mmap flag that optimizes allocation/deallocation of
114// giant memory regions (i.e. shadow memory regions).
115#define kXnuFastMmapFd 0x4
116static size_t kXnuFastMmapThreshold = 2 << 30; // 2 GB
117static bool use_xnu_fast_mmap = false;
118
119uptr internal_mmap(void *addr, size_t length, int prot, int flags,
120 int fd, u64 offset) {
121 if (fd == -1) {
122 fd = VM_MAKE_TAG(VM_MEMORY_SANITIZER);
123 if (length >= kXnuFastMmapThreshold) {
124 if (use_xnu_fast_mmap) fd |= kXnuFastMmapFd;
125 }
126 }
127 if (&__mmap) return (uptr)__mmap(addr, length, prot, flags, fd, offset);
128 return (uptr)mmap(addr, length, prot, flags, fd, offset);
129}
130
131uptr internal_munmap(void *addr, uptr length) {
132 if (&__munmap) return __munmap(addr, length);
133 return munmap(addr, length);
134}
135
136int internal_mprotect(void *addr, uptr length, int prot) {
137 return mprotect(addr, length, prot);
138}
139
140uptr internal_close(fd_t fd) {
141 return close(fd);
142}
143
144uptr internal_open(const char *filename, int flags) {
145 return open(filename, flags);
146}
147
148uptr internal_open(const char *filename, int flags, u32 mode) {
149 return open(filename, flags, mode);
150}
151
152uptr internal_read(fd_t fd, void *buf, uptr count) {
153 return read(fd, buf, count);
154}
155
156uptr internal_write(fd_t fd, const void *buf, uptr count) {
157 return write(fd, buf, count);
158}
159
160uptr internal_stat(const char *path, void *buf) {
161 return stat(path, (struct stat *)buf);
162}
163
164uptr internal_lstat(const char *path, void *buf) {
165 return lstat(path, (struct stat *)buf);
166}
167
168uptr internal_fstat(fd_t fd, void *buf) {
169 return fstat(fd, (struct stat *)buf);
170}
171
172uptr internal_filesize(fd_t fd) {
173 struct stat st;
174 if (internal_fstat(fd, &st))
175 return -1;
176 return (uptr)st.st_size;
177}
178
179uptr internal_dup(int oldfd) {
180 return dup(oldfd);
181}
182
183uptr internal_dup2(int oldfd, int newfd) {
184 return dup2(oldfd, newfd);
185}
186
187uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
188 return readlink(path, buf, bufsize);
189}
190
191uptr internal_unlink(const char *path) {
192 return unlink(path);
193}
194
195uptr internal_sched_yield() {
196 return sched_yield();
197}
198
199void internal__exit(int exitcode) {
200 _exit(exitcode);
201}
202
203unsigned int internal_sleep(unsigned int seconds) {
204 return sleep(seconds);
205}
206
207uptr internal_getpid() {
208 return getpid();
209}
210
211int internal_dlinfo(void *handle, int request, void *p) {
212 UNIMPLEMENTED();
213}
214
215int internal_sigaction(int signum, const void *act, void *oldact) {
216 return sigaction(signum,
217 (const struct sigaction *)act, (struct sigaction *)oldact);
218}
219
220void internal_sigfillset(__sanitizer_sigset_t *set) { sigfillset(set); }
221
222uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set,
223 __sanitizer_sigset_t *oldset) {
224 // Don't use sigprocmask here, because it affects all threads.
225 return pthread_sigmask(how, set, oldset);
226}
227
228// Doesn't call pthread_atfork() handlers (but not available on 10.6).
229extern "C" pid_t __fork(void) SANITIZER_WEAK_ATTRIBUTE;
230
231int internal_fork() {
232 if (&__fork)
233 return __fork();
234 return fork();
235}
236
237int internal_sysctl(const int *name, unsigned int namelen, void *oldp,
238 uptr *oldlenp, const void *newp, uptr newlen) {
239 return sysctl(const_cast<int *>(name), namelen, oldp, (size_t *)oldlenp,
240 const_cast<void *>(newp), (size_t)newlen);
241}
242
243int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp,
244 const void *newp, uptr newlen) {
245 return sysctlbyname(sname, oldp, (size_t *)oldlenp, const_cast<void *>(newp),
246 (size_t)newlen);
247}
248
249static fd_t internal_spawn_impl(const char *argv[], const char *envp[],
250 pid_t *pid) {
251 fd_t master_fd = kInvalidFd;
252 fd_t slave_fd = kInvalidFd;
253
254 auto fd_closer = at_scope_exit([&] {
255 internal_close(master_fd);
256 internal_close(slave_fd);
257 });
258
259 // We need a new pseudoterminal to avoid buffering problems. The 'atos' tool
260 // in particular detects when it's talking to a pipe and forgets to flush the
261 // output stream after sending a response.
262 master_fd = posix_openpt(O_RDWR);
263 if (master_fd == kInvalidFd) return kInvalidFd;
264
265 int res = grantpt(master_fd) || unlockpt(master_fd);
266 if (res != 0) return kInvalidFd;
267
268 // Use TIOCPTYGNAME instead of ptsname() to avoid threading problems.
269 char slave_pty_name[128];
270 res = ioctl(master_fd, TIOCPTYGNAME, slave_pty_name);
271 if (res == -1) return kInvalidFd;
272
273 slave_fd = internal_open(slave_pty_name, O_RDWR);
274 if (slave_fd == kInvalidFd) return kInvalidFd;
275
276 // File descriptor actions
277 posix_spawn_file_actions_t acts;
278 res = posix_spawn_file_actions_init(&acts);
279 if (res != 0) return kInvalidFd;
280
281 auto acts_cleanup = at_scope_exit([&] {
282 posix_spawn_file_actions_destroy(&acts);
283 });
284
285 res = posix_spawn_file_actions_adddup2(&acts, slave_fd, STDIN_FILENO) ||
286 posix_spawn_file_actions_adddup2(&acts, slave_fd, STDOUT_FILENO) ||
287 posix_spawn_file_actions_addclose(&acts, slave_fd);
288 if (res != 0) return kInvalidFd;
289
290 // Spawn attributes
291 posix_spawnattr_t attrs;
292 res = posix_spawnattr_init(&attrs);
293 if (res != 0) return kInvalidFd;
294
295 auto attrs_cleanup = at_scope_exit([&] {
296 posix_spawnattr_destroy(&attrs);
297 });
298
299 // In the spawned process, close all file descriptors that are not explicitly
300 // described by the file actions object. This is Darwin-specific extension.
301 res = posix_spawnattr_setflags(&attrs, POSIX_SPAWN_CLOEXEC_DEFAULT);
302 if (res != 0) return kInvalidFd;
303
304 // posix_spawn
305 char **argv_casted = const_cast<char **>(argv);
306 char **envp_casted = const_cast<char **>(envp);
307 res = posix_spawn(pid, argv[0], &acts, &attrs, argv_casted, envp_casted);
308 if (res != 0) return kInvalidFd;
309
310 // Disable echo in the new terminal, disable CR.
311 struct termios termflags;
312 tcgetattr(master_fd, &termflags);
313 termflags.c_oflag &= ~ONLCR;
314 termflags.c_lflag &= ~ECHO;
315 tcsetattr(master_fd, TCSANOW, &termflags);
316
317 // On success, do not close master_fd on scope exit.
318 fd_t fd = master_fd;
319 master_fd = kInvalidFd;
320
321 return fd;
322}
323
324fd_t internal_spawn(const char *argv[], const char *envp[], pid_t *pid) {
325 // The client program may close its stdin and/or stdout and/or stderr thus
326 // allowing open/posix_openpt to reuse file descriptors 0, 1 or 2. In this
327 // case the communication is broken if either the parent or the child tries to
328 // close or duplicate these descriptors. We temporarily reserve these
329 // descriptors here to prevent this.
330 fd_t low_fds[3];
331 size_t count = 0;
332
333 for (; count < 3; count++) {
334 low_fds[count] = posix_openpt(O_RDWR);
335 if (low_fds[count] >= STDERR_FILENO)
336 break;
337 }
338
339 fd_t fd = internal_spawn_impl(argv, envp, pid);
340
341 for (; count > 0; count--) {
342 internal_close(low_fds[count]);
343 }
344
345 return fd;
346}
347
348uptr internal_rename(const char *oldpath, const char *newpath) {
349 return rename(oldpath, newpath);
350}
351
352uptr internal_ftruncate(fd_t fd, uptr size) {
353 return ftruncate(fd, size);
354}
355
356uptr internal_execve(const char *filename, char *const argv[],
357 char *const envp[]) {
358 return execve(filename, argv, envp);
359}
360
361uptr internal_waitpid(int pid, int *status, int options) {
362 return waitpid(pid, status, options);
363}
364
365// ----------------- sanitizer_common.h
366bool FileExists(const char *filename) {
367 if (ShouldMockFailureToOpen(filename))
368 return false;
369 struct stat st;
370 if (stat(filename, &st))
371 return false;
372 // Sanity check: filename is a regular file.
373 return S_ISREG(st.st_mode);
374}
375
376tid_t GetTid() {
377 tid_t tid;
378 pthread_threadid_np(nullptr, &tid);
379 return tid;
380}
381
382void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
383 uptr *stack_bottom) {
384 CHECK(stack_top);
385 CHECK(stack_bottom);
386 uptr stacksize = pthread_get_stacksize_np(pthread_self());
387 // pthread_get_stacksize_np() returns an incorrect stack size for the main
388 // thread on Mavericks. See
389 // https://github.com/google/sanitizers/issues/261
390 if ((GetMacosAlignedVersion() >= MacosVersion(10, 9)) && at_initialization &&
391 stacksize == (1 << 19)) {
392 struct rlimit rl;
393 CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0);
394 // Most often rl.rlim_cur will be the desired 8M.
395 if (rl.rlim_cur < kMaxThreadStackSize) {
396 stacksize = rl.rlim_cur;
397 } else {
398 stacksize = kMaxThreadStackSize;
399 }
400 }
401 void *stackaddr = pthread_get_stackaddr_np(pthread_self());
402 *stack_top = (uptr)stackaddr;
403 *stack_bottom = *stack_top - stacksize;
404}
405
406char **GetEnviron() {
407#if !SANITIZER_IOS
408 char ***env_ptr = _NSGetEnviron();
409 if (!env_ptr) {
410 Report("_NSGetEnviron() returned NULL. Please make sure __asan_init() is "
411 "called after libSystem_initializer().\n");
412 CHECK(env_ptr);
413 }
414 char **environ = *env_ptr;
415#endif
416 CHECK(environ);
417 return environ;
418}
419
420const char *GetEnv(const char *name) {
421 char **env = GetEnviron();
422 uptr name_len = internal_strlen(name);
423 while (*env != 0) {
424 uptr len = internal_strlen(*env);
425 if (len > name_len) {
426 const char *p = *env;
427 if (!internal_memcmp(p, name, name_len) &&
428 p[name_len] == '=') { // Match.
429 return *env + name_len + 1; // String starting after =.
430 }
431 }
432 env++;
433 }
434 return 0;
435}
436
437uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
438 CHECK_LE(kMaxPathLength, buf_len);
439
440 // On OS X the executable path is saved to the stack by dyld. Reading it
441 // from there is much faster than calling dladdr, especially for large
442 // binaries with symbols.
443 InternalScopedString exe_path(kMaxPathLength);
444 uint32_t size = exe_path.size();
445 if (_NSGetExecutablePath(exe_path.data(), &size) == 0 &&
446 realpath(exe_path.data(), buf) != 0) {
447 return internal_strlen(buf);
448 }
449 return 0;
450}
451
452uptr ReadLongProcessName(/*out*/char *buf, uptr buf_len) {
453 return ReadBinaryName(buf, buf_len);
454}
455
456void ReExec() {
457 UNIMPLEMENTED();
458}
459
460void CheckASLR() {
461 // Do nothing
462}
463
464void CheckMPROTECT() {
465 // Do nothing
466}
467
468uptr GetPageSize() {
469 return sysconf(_SC_PAGESIZE);
470}
471
472extern "C" unsigned malloc_num_zones;
473extern "C" malloc_zone_t **malloc_zones;
474malloc_zone_t sanitizer_zone;
475
476// We need to make sure that sanitizer_zone is registered as malloc_zones[0]. If
477// libmalloc tries to set up a different zone as malloc_zones[0], it will call
478// mprotect(malloc_zones, ..., PROT_READ). This interceptor will catch that and
479// make sure we are still the first (default) zone.
480void MprotectMallocZones(void *addr, int prot) {
481 if (addr == malloc_zones && prot == PROT_READ) {
482 if (malloc_num_zones > 1 && malloc_zones[0] != &sanitizer_zone) {
483 for (unsigned i = 1; i < malloc_num_zones; i++) {
484 if (malloc_zones[i] == &sanitizer_zone) {
485 // Swap malloc_zones[0] and malloc_zones[i].
486 malloc_zones[i] = malloc_zones[0];
487 malloc_zones[0] = &sanitizer_zone;
488 break;
489 }
490 }
491 }
492 }
493}
494
495BlockingMutex::BlockingMutex() {
496 internal_memset(this, 0, sizeof(*this));
497}
498
499void BlockingMutex::Lock() {
500 CHECK(sizeof(OSSpinLock) <= sizeof(opaque_storage_));
501 CHECK_EQ(OS_SPINLOCK_INIT, 0);
502 CHECK_EQ(owner_, 0);
503 OSSpinLockLock((OSSpinLock*)&opaque_storage_);
504}
505
506void BlockingMutex::Unlock() {
507 OSSpinLockUnlock((OSSpinLock*)&opaque_storage_);
508}
509
510void BlockingMutex::CheckLocked() {
511 CHECK_NE(*(OSSpinLock*)&opaque_storage_, 0);
512}
513
514u64 NanoTime() {
515 timeval tv;
516 internal_memset(&tv, 0, sizeof(tv));
517 gettimeofday(&tv, 0);
518 return (u64)tv.tv_sec * 1000*1000*1000 + tv.tv_usec * 1000;
519}
520
521// This needs to be called during initialization to avoid being racy.
522u64 MonotonicNanoTime() {
523 static mach_timebase_info_data_t timebase_info;
524 if (timebase_info.denom == 0) mach_timebase_info(&timebase_info);
525 return (mach_absolute_time() * timebase_info.numer) / timebase_info.denom;
526}
527
528uptr GetTlsSize() {
529 return 0;
530}
531
532void InitTlsSize() {
533}
534
535uptr TlsBaseAddr() {
536 uptr segbase = 0;
537#if defined(__x86_64__)
538 asm("movq %%gs:0,%0" : "=r"(segbase));
539#elif defined(__i386__)
540 asm("movl %%gs:0,%0" : "=r"(segbase));
541#endif
542 return segbase;
543}
544
545// The size of the tls on darwin does not appear to be well documented,
546// however the vm memory map suggests that it is 1024 uptrs in size,
547// with a size of 0x2000 bytes on x86_64 and 0x1000 bytes on i386.
548uptr TlsSize() {
549#if defined(__x86_64__) || defined(__i386__)
550 return 1024 * sizeof(uptr);
551#else
552 return 0;
553#endif
554}
555
556void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
557 uptr *tls_addr, uptr *tls_size) {
558#if !SANITIZER_GO
559 uptr stack_top, stack_bottom;
560 GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
561 *stk_addr = stack_bottom;
562 *stk_size = stack_top - stack_bottom;
563 *tls_addr = TlsBaseAddr();
564 *tls_size = TlsSize();
565#else
566 *stk_addr = 0;
567 *stk_size = 0;
568 *tls_addr = 0;
569 *tls_size = 0;
570#endif
571}
572
573void ListOfModules::init() {
574 clearOrInit();
575 MemoryMappingLayout memory_mapping(false);
576 memory_mapping.DumpListOfModules(&modules_);
577}
578
579void ListOfModules::fallbackInit() { clear(); }
580
581static HandleSignalMode GetHandleSignalModeImpl(int signum) {
582 switch (signum) {
583 case SIGABRT:
584 return common_flags()->handle_abort;
585 case SIGILL:
586 return common_flags()->handle_sigill;
587 case SIGTRAP:
588 return common_flags()->handle_sigtrap;
589 case SIGFPE:
590 return common_flags()->handle_sigfpe;
591 case SIGSEGV:
592 return common_flags()->handle_segv;
593 case SIGBUS:
594 return common_flags()->handle_sigbus;
595 }
596 return kHandleSignalNo;
597}
598
599HandleSignalMode GetHandleSignalMode(int signum) {
600 // Handling fatal signals on watchOS and tvOS devices is disallowed.
601 if ((SANITIZER_WATCHOS || SANITIZER_TVOS) && !(SANITIZER_IOSSIM))
602 return kHandleSignalNo;
603 HandleSignalMode result = GetHandleSignalModeImpl(signum);
604 if (result == kHandleSignalYes && !common_flags()->allow_user_segv_handler)
605 return kHandleSignalExclusive;
606 return result;
607}
608
609// This corresponds to Triple::getMacOSXVersion() in the Clang driver.
610static MacosVersion GetMacosAlignedVersionInternal() {
611 u16 kernel_major = GetDarwinKernelVersion().major;
612 // Darwin 0-3 -> unsupported
613 // Darwin 4-19 -> macOS 10.x
614 // Darwin 20+ -> macOS 11+
615 CHECK_GE(kernel_major, 4);
616 u16 major, minor;
617 if (kernel_major < 20) {
618 major = 10;
619 minor = kernel_major - 4;
620 } else {
621 major = 11 + kernel_major - 20;
622 minor = 0;
623 }
624 return MacosVersion(major, minor);
625}
626
627static_assert(sizeof(MacosVersion) == sizeof(atomic_uint32_t::Type),
628 "MacosVersion cache size");
629static atomic_uint32_t cached_macos_version;
630
631MacosVersion GetMacosAlignedVersion() {
632 atomic_uint32_t::Type result =
633 atomic_load(&cached_macos_version, memory_order_acquire);
634 if (!result) {
635 MacosVersion version = GetMacosAlignedVersionInternal();
636 result = *reinterpret_cast<atomic_uint32_t::Type *>(&version);
637 atomic_store(&cached_macos_version, result, memory_order_release);
638 }
639 return *reinterpret_cast<MacosVersion *>(&result);
640}
641
642void ParseVersion(const char *vers, u16 *major, u16 *minor) {
643 // Format: <major>.<minor>.<patch>\0
644 CHECK_GE(internal_strlen(vers), 5);
645 const char *p = vers;
646 *major = internal_simple_strtoll(p, &p, /*base=*/10);
647 CHECK_EQ(*p, '.');
648 p += 1;
649 *minor = internal_simple_strtoll(p, &p, /*base=*/10);
650}
651
652DarwinKernelVersion GetDarwinKernelVersion() {
653 char buf[100];
654 size_t len = sizeof(buf);
655 int res = internal_sysctlbyname("kern.osrelease", buf, &len, nullptr, 0);
656 CHECK_EQ(res, 0);
657
658 u16 major, minor;
659 ParseVersion(buf, &major, &minor);
660
661 return DarwinKernelVersion(major, minor);
662}
663
664uptr GetRSS() {
665 struct task_basic_info info;
666 unsigned count = TASK_BASIC_INFO_COUNT;
667 kern_return_t result =
668 task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &count);
669 if (UNLIKELY(result != KERN_SUCCESS)) {
670 Report("Cannot get task info. Error: %d\n", result);
671 Die();
672 }
673 return info.resident_size;
674}
675
676void *internal_start_thread(void *(*func)(void *arg), void *arg) {
677 // Start the thread with signals blocked, otherwise it can steal user signals.
678 __sanitizer_sigset_t set, old;
679 internal_sigfillset(&set);
680 internal_sigprocmask(SIG_SETMASK, &set, &old);
681 pthread_t th;
682 pthread_create(&th, 0, func, arg);
683 internal_sigprocmask(SIG_SETMASK, &old, 0);
684 return th;
685}
686
687void internal_join_thread(void *th) { pthread_join((pthread_t)th, 0); }
688
689#if !SANITIZER_GO
690static BlockingMutex syslog_lock(LINKER_INITIALIZED);
691#endif
692
693void WriteOneLineToSyslog(const char *s) {
694#if !SANITIZER_GO
695 syslog_lock.CheckLocked();
696 asl_log(nullptr, nullptr, ASL_LEVEL_ERR, "%s", s);
697#endif
698}
699
700void LogMessageOnPrintf(const char *str) {
701 // Log all printf output to CrashLog.
702 if (common_flags()->abort_on_error)
703 CRAppendCrashLogMessage(str);
704}
705
706void LogFullErrorReport(const char *buffer) {
707#if !SANITIZER_GO
708 // Log with os_trace. This will make it into the crash log.
709#if SANITIZER_OS_TRACE
710 if (GetMacosAlignedVersion() >= MacosVersion(10, 10)) {
711 // os_trace requires the message (format parameter) to be a string literal.
712 if (internal_strncmp(SanitizerToolName, "AddressSanitizer",
713 sizeof("AddressSanitizer") - 1) == 0)
714 os_trace("Address Sanitizer reported a failure.");
715 else if (internal_strncmp(SanitizerToolName, "UndefinedBehaviorSanitizer",
716 sizeof("UndefinedBehaviorSanitizer") - 1) == 0)
717 os_trace("Undefined Behavior Sanitizer reported a failure.");
718 else if (internal_strncmp(SanitizerToolName, "ThreadSanitizer",
719 sizeof("ThreadSanitizer") - 1) == 0)
720 os_trace("Thread Sanitizer reported a failure.");
721 else
722 os_trace("Sanitizer tool reported a failure.");
723
724 if (common_flags()->log_to_syslog)
725 os_trace("Consult syslog for more information.");
726 }
727#endif
728
729 // Log to syslog.
730 // The logging on OS X may call pthread_create so we need the threading
731 // environment to be fully initialized. Also, this should never be called when
732 // holding the thread registry lock since that may result in a deadlock. If
733 // the reporting thread holds the thread registry mutex, and asl_log waits
734 // for GCD to dispatch a new thread, the process will deadlock, because the
735 // pthread_create wrapper needs to acquire the lock as well.
736 BlockingMutexLock l(&syslog_lock);
737 if (common_flags()->log_to_syslog)
738 WriteToSyslog(buffer);
739
740 // The report is added to CrashLog as part of logging all of Printf output.
741#endif
742}
743
744SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
745#if defined(__x86_64__) || defined(__i386__)
746 ucontext_t *ucontext = static_cast<ucontext_t*>(context);
747 return ucontext->uc_mcontext->__es.__err & 2 /*T_PF_WRITE*/ ? WRITE : READ;
748#else
749 return UNKNOWN;
750#endif
751}
752
753bool SignalContext::IsTrueFaultingAddress() const {
754 auto si = static_cast<const siginfo_t *>(siginfo);
755 // "Real" SIGSEGV codes (e.g., SEGV_MAPERR, SEGV_MAPERR) are non-zero.
756 return si->si_signo == SIGSEGV && si->si_code != 0;
757}
758
759#if defined(__aarch64__) && defined(arm_thread_state64_get_sp)
760 #define AARCH64_GET_REG(r) \
761 (uptr)ptrauth_strip( \
762 (void *)arm_thread_state64_get_##r(ucontext->uc_mcontext->__ss), 0)
763#else
764 #define AARCH64_GET_REG(r) ucontext->uc_mcontext->__ss.__##r
765#endif
766
767static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
768 ucontext_t *ucontext = (ucontext_t*)context;
769# if defined(__aarch64__)
770 *pc = AARCH64_GET_REG(pc);
771# if defined(__IPHONE_8_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_8_0
772 *bp = AARCH64_GET_REG(fp);
773# else
774 *bp = AARCH64_GET_REG(lr);
775# endif
776 *sp = AARCH64_GET_REG(sp);
777# elif defined(__x86_64__)
778 *pc = ucontext->uc_mcontext->__ss.__rip;
779 *bp = ucontext->uc_mcontext->__ss.__rbp;
780 *sp = ucontext->uc_mcontext->__ss.__rsp;
781# elif defined(__arm__)
782 *pc = ucontext->uc_mcontext->__ss.__pc;
783 *bp = ucontext->uc_mcontext->__ss.__r[7];
784 *sp = ucontext->uc_mcontext->__ss.__sp;
785# elif defined(__i386__)
786 *pc = ucontext->uc_mcontext->__ss.__eip;
787 *bp = ucontext->uc_mcontext->__ss.__ebp;
788 *sp = ucontext->uc_mcontext->__ss.__esp;
789# else
790# error "Unknown architecture"
791# endif
792}
793
794void SignalContext::InitPcSpBp() {
795 addr = (uptr)ptrauth_strip((void *)addr, 0);
796 GetPcSpBp(context, &pc, &sp, &bp);
797}
798
799void InitializePlatformEarly() {
800 // Only use xnu_fast_mmap when on x86_64 and the kernel supports it.
801 use_xnu_fast_mmap =
802#if defined(__x86_64__)
803 GetDarwinKernelVersion() >= DarwinKernelVersion(17, 5);
804#else
805 false;
806#endif
807}
808
809#if !SANITIZER_GO
810static const char kDyldInsertLibraries[] = "DYLD_INSERT_LIBRARIES";
811LowLevelAllocator allocator_for_env;
812
813// Change the value of the env var |name|, leaking the original value.
814// If |name_value| is NULL, the variable is deleted from the environment,
815// otherwise the corresponding "NAME=value" string is replaced with
816// |name_value|.
817void LeakyResetEnv(const char *name, const char *name_value) {
818 char **env = GetEnviron();
819 uptr name_len = internal_strlen(name);
820 while (*env != 0) {
821 uptr len = internal_strlen(*env);
822 if (len > name_len) {
823 const char *p = *env;
824 if (!internal_memcmp(p, name, name_len) && p[name_len] == '=') {
825 // Match.
826 if (name_value) {
827 // Replace the old value with the new one.
828 *env = const_cast<char*>(name_value);
829 } else {
830 // Shift the subsequent pointers back.
831 char **del = env;
832 do {
833 del[0] = del[1];
834 } while (*del++);
835 }
836 }
837 }
838 env++;
839 }
840}
841
842SANITIZER_WEAK_CXX_DEFAULT_IMPL
843bool ReexecDisabled() {
844 return false;
845}
846
847extern "C" SANITIZER_WEAK_ATTRIBUTE double dyldVersionNumber;
848static const double kMinDyldVersionWithAutoInterposition = 360.0;
849
850bool DyldNeedsEnvVariable() {
851 // Although sanitizer support was added to LLVM on OS X 10.7+, GCC users
852 // still may want use them on older systems. On older Darwin platforms, dyld
853 // doesn't export dyldVersionNumber symbol and we simply return true.
854 if (!&dyldVersionNumber) return true;
855 // If running on OS X 10.11+ or iOS 9.0+, dyld will interpose even if
856 // DYLD_INSERT_LIBRARIES is not set. However, checking OS version via
857 // GetMacosAlignedVersion() doesn't work for the simulator. Let's instead
858 // check `dyldVersionNumber`, which is exported by dyld, against a known
859 // version number from the first OS release where this appeared.
860 return dyldVersionNumber < kMinDyldVersionWithAutoInterposition;
861}
862
863void MaybeReexec() {
864 // FIXME: This should really live in some "InitializePlatform" method.
865 MonotonicNanoTime();
866
867 if (ReexecDisabled()) return;
868
869 // Make sure the dynamic runtime library is preloaded so that the
870 // wrappers work. If it is not, set DYLD_INSERT_LIBRARIES and re-exec
871 // ourselves.
872 Dl_info info;
873 RAW_CHECK(dladdr((void*)((uptr)&__sanitizer_report_error_summary), &info));
874 char *dyld_insert_libraries =
875 const_cast<char*>(GetEnv(kDyldInsertLibraries));
876 uptr old_env_len = dyld_insert_libraries ?
877 internal_strlen(dyld_insert_libraries) : 0;
878 uptr fname_len = internal_strlen(info.dli_fname);
879 const char *dylib_name = StripModuleName(info.dli_fname);
880 uptr dylib_name_len = internal_strlen(dylib_name);
881
882 bool lib_is_in_env = dyld_insert_libraries &&
883 internal_strstr(dyld_insert_libraries, dylib_name);
884 if (DyldNeedsEnvVariable() && !lib_is_in_env) {
885 // DYLD_INSERT_LIBRARIES is not set or does not contain the runtime
886 // library.
887 InternalScopedString program_name(1024);
888 uint32_t buf_size = program_name.size();
889 _NSGetExecutablePath(program_name.data(), &buf_size);
890 char *new_env = const_cast<char*>(info.dli_fname);
891 if (dyld_insert_libraries) {
892 // Append the runtime dylib name to the existing value of
893 // DYLD_INSERT_LIBRARIES.
894 new_env = (char*)allocator_for_env.Allocate(old_env_len + fname_len + 2);
895 internal_strncpy(new_env, dyld_insert_libraries, old_env_len);
896 new_env[old_env_len] = ':';
897 // Copy fname_len and add a trailing zero.
898 internal_strncpy(new_env + old_env_len + 1, info.dli_fname,
899 fname_len + 1);
900 // Ok to use setenv() since the wrappers don't depend on the value of
901 // asan_inited.
902 setenv(kDyldInsertLibraries, new_env, /*overwrite*/1);
903 } else {
904 // Set DYLD_INSERT_LIBRARIES equal to the runtime dylib name.
905 setenv(kDyldInsertLibraries, info.dli_fname, /*overwrite*/0);
906 }
907 VReport(1, "exec()-ing the program with\n");
908 VReport(1, "%s=%s\n", kDyldInsertLibraries, new_env);
909 VReport(1, "to enable wrappers.\n");
910 execv(program_name.data(), *_NSGetArgv());
911
912 // We get here only if execv() failed.
913 Report("ERROR: The process is launched without DYLD_INSERT_LIBRARIES, "
914 "which is required for the sanitizer to work. We tried to set the "
915 "environment variable and re-execute itself, but execv() failed, "
916 "possibly because of sandbox restrictions. Make sure to launch the "
917 "executable with:\n%s=%s\n", kDyldInsertLibraries, new_env);
918 RAW_CHECK("execv failed" && 0);
919 }
920
921 // Verify that interceptors really work. We'll use dlsym to locate
922 // "pthread_create", if interceptors are working, it should really point to
923 // "wrap_pthread_create" within our own dylib.
924 Dl_info info_pthread_create;
925 void *dlopen_addr = dlsym(RTLD_DEFAULT, "pthread_create");
926 RAW_CHECK(dladdr(dlopen_addr, &info_pthread_create));
927 if (internal_strcmp(info.dli_fname, info_pthread_create.dli_fname) != 0) {
928 Report(
929 "ERROR: Interceptors are not working. This may be because %s is "
930 "loaded too late (e.g. via dlopen). Please launch the executable "
931 "with:\n%s=%s\n",
932 SanitizerToolName, kDyldInsertLibraries, info.dli_fname);
933 RAW_CHECK("interceptors not installed" && 0);
934 }
935
936 if (!lib_is_in_env)
937 return;
938
939 if (!common_flags()->strip_env)
940 return;
941
942 // DYLD_INSERT_LIBRARIES is set and contains the runtime library. Let's remove
943 // the dylib from the environment variable, because interceptors are installed
944 // and we don't want our children to inherit the variable.
945
946 uptr env_name_len = internal_strlen(kDyldInsertLibraries);
947 // Allocate memory to hold the previous env var name, its value, the '='
948 // sign and the '\0' char.
949 char *new_env = (char*)allocator_for_env.Allocate(
950 old_env_len + 2 + env_name_len);
951 RAW_CHECK(new_env);
952 internal_memset(new_env, '\0', old_env_len + 2 + env_name_len);
953 internal_strncpy(new_env, kDyldInsertLibraries, env_name_len);
954 new_env[env_name_len] = '=';
955 char *new_env_pos = new_env + env_name_len + 1;
956
957 // Iterate over colon-separated pieces of |dyld_insert_libraries|.
958 char *piece_start = dyld_insert_libraries;
959 char *piece_end = NULL;
960 char *old_env_end = dyld_insert_libraries + old_env_len;
961 do {
962 if (piece_start[0] == ':') piece_start++;
963 piece_end = internal_strchr(piece_start, ':');
964 if (!piece_end) piece_end = dyld_insert_libraries + old_env_len;
965 if ((uptr)(piece_start - dyld_insert_libraries) > old_env_len) break;
966 uptr piece_len = piece_end - piece_start;
967
968 char *filename_start =
969 (char *)internal_memrchr(piece_start, '/', piece_len);
970 uptr filename_len = piece_len;
971 if (filename_start) {
972 filename_start += 1;
973 filename_len = piece_len - (filename_start - piece_start);
974 } else {
975 filename_start = piece_start;
976 }
977
978 // If the current piece isn't the runtime library name,
979 // append it to new_env.
980 if ((dylib_name_len != filename_len) ||
981 (internal_memcmp(filename_start, dylib_name, dylib_name_len) != 0)) {
982 if (new_env_pos != new_env + env_name_len + 1) {
983 new_env_pos[0] = ':';
984 new_env_pos++;
985 }
986 internal_strncpy(new_env_pos, piece_start, piece_len);
987 new_env_pos += piece_len;
988 }
989 // Move on to the next piece.
990 piece_start = piece_end;
991 } while (piece_start < old_env_end);
992
993 // Can't use setenv() here, because it requires the allocator to be
994 // initialized.
995 // FIXME: instead of filtering DYLD_INSERT_LIBRARIES here, do it in
996 // a separate function called after InitializeAllocator().
997 if (new_env_pos == new_env + env_name_len + 1) new_env = NULL;
998 LeakyResetEnv(kDyldInsertLibraries, new_env);
999}
1000#endif // SANITIZER_GO
1001
1002char **GetArgv() {
1003 return *_NSGetArgv();
1004}
1005
1006#if SANITIZER_IOS
1007// The task_vm_info struct is normally provided by the macOS SDK, but we need
1008// fields only available in 10.12+. Declare the struct manually to be able to
1009// build against older SDKs.
1010struct __sanitizer_task_vm_info {
1011 mach_vm_size_t virtual_size;
1012 integer_t region_count;
1013 integer_t page_size;
1014 mach_vm_size_t resident_size;
1015 mach_vm_size_t resident_size_peak;
1016 mach_vm_size_t device;
1017 mach_vm_size_t device_peak;
1018 mach_vm_size_t internal;
1019 mach_vm_size_t internal_peak;
1020 mach_vm_size_t external;
1021 mach_vm_size_t external_peak;
1022 mach_vm_size_t reusable;
1023 mach_vm_size_t reusable_peak;
1024 mach_vm_size_t purgeable_volatile_pmap;
1025 mach_vm_size_t purgeable_volatile_resident;
1026 mach_vm_size_t purgeable_volatile_virtual;
1027 mach_vm_size_t compressed;
1028 mach_vm_size_t compressed_peak;
1029 mach_vm_size_t compressed_lifetime;
1030 mach_vm_size_t phys_footprint;
1031 mach_vm_address_t min_address;
1032 mach_vm_address_t max_address;
1033};
1034#define __SANITIZER_TASK_VM_INFO_COUNT ((mach_msg_type_number_t) \
1035 (sizeof(__sanitizer_task_vm_info) / sizeof(natural_t)))
1036
1037static uptr GetTaskInfoMaxAddress() {
1038 __sanitizer_task_vm_info vm_info = {} /* zero initialize */;
1039 mach_msg_type_number_t count = __SANITIZER_TASK_VM_INFO_COUNT;
1040 int err = task_info(mach_task_self(), TASK_VM_INFO, (int *)&vm_info, &count);
1041 return err ? 0 : vm_info.max_address;
1042}
1043
1044uptr GetMaxUserVirtualAddress() {
1045 static uptr max_vm = GetTaskInfoMaxAddress();
1046 if (max_vm != 0)
1047 return max_vm - 1;
1048
1049 // xnu cannot provide vm address limit
1050# if SANITIZER_WORDSIZE == 32
1051 return 0xffe00000 - 1;
1052# else
1053 return 0x200000000 - 1;
1054# endif
1055}
1056
1057#else // !SANITIZER_IOS
1058
1059uptr GetMaxUserVirtualAddress() {
1060# if SANITIZER_WORDSIZE == 64
1061 return (1ULL << 47) - 1; // 0x00007fffffffffffUL;
1062# else // SANITIZER_WORDSIZE == 32
1063 static_assert(SANITIZER_WORDSIZE == 32, "Wrong wordsize");
1064 return (1ULL << 32) - 1; // 0xffffffff;
1065# endif
1066}
1067#endif
1068
1069uptr GetMaxVirtualAddress() {
1070 return GetMaxUserVirtualAddress();
1071}
1072
1073uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,
1074 uptr *largest_gap_found,
1075 uptr *max_occupied_addr) {
1076 typedef vm_region_submap_short_info_data_64_t RegionInfo;
1077 enum { kRegionInfoSize = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64 };
1078 // Start searching for available memory region past PAGEZERO, which is
1079 // 4KB on 32-bit and 4GB on 64-bit.
1080 mach_vm_address_t start_address =
1081 (SANITIZER_WORDSIZE == 32) ? 0x000000001000 : 0x000100000000;
1082
1083 mach_vm_address_t address = start_address;
1084 mach_vm_address_t free_begin = start_address;
1085 kern_return_t kr = KERN_SUCCESS;
1086 if (largest_gap_found) *largest_gap_found = 0;
1087 if (max_occupied_addr) *max_occupied_addr = 0;
1088 while (kr == KERN_SUCCESS) {
1089 mach_vm_size_t vmsize = 0;
1090 natural_t depth = 0;
1091 RegionInfo vminfo;
1092 mach_msg_type_number_t count = kRegionInfoSize;
1093 kr = mach_vm_region_recurse(mach_task_self(), &address, &vmsize, &depth,
1094 (vm_region_info_t)&vminfo, &count);
1095 if (kr == KERN_INVALID_ADDRESS) {
1096 // No more regions beyond "address", consider the gap at the end of VM.
1097 address = GetMaxVirtualAddress() + 1;
1098 vmsize = 0;
1099 } else {
1100 if (max_occupied_addr) *max_occupied_addr = address + vmsize;
1101 }
1102 if (free_begin != address) {
1103 // We found a free region [free_begin..address-1].
1104 uptr gap_start = RoundUpTo((uptr)free_begin + left_padding, alignment);
1105 uptr gap_end = RoundDownTo((uptr)address, alignment);
1106 uptr gap_size = gap_end > gap_start ? gap_end - gap_start : 0;
1107 if (size < gap_size) {
1108 return gap_start;
1109 }
1110
1111 if (largest_gap_found && *largest_gap_found < gap_size) {
1112 *largest_gap_found = gap_size;
1113 }
1114 }
1115 // Move to the next region.
1116 address += vmsize;
1117 free_begin = address;
1118 }
1119
1120 // We looked at all free regions and could not find one large enough.
1121 return 0;
1122}
1123
1124// FIXME implement on this platform.
1125void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size) { }
1126
1127void SignalContext::DumpAllRegisters(void *context) {
1128 Report("Register values:\n");
1129
1130 ucontext_t *ucontext = (ucontext_t*)context;
1131# define DUMPREG64(r) \
1132 Printf("%s = 0x%016llx ", #r, ucontext->uc_mcontext->__ss.__ ## r);
1133# define DUMPREGA64(r) \
1134 Printf(" %s = 0x%016llx ", #r, AARCH64_GET_REG(r));
1135# define DUMPREG32(r) \
1136 Printf("%s = 0x%08x ", #r, ucontext->uc_mcontext->__ss.__ ## r);
1137# define DUMPREG_(r) Printf(" "); DUMPREG(r);
1138# define DUMPREG__(r) Printf(" "); DUMPREG(r);
1139# define DUMPREG___(r) Printf(" "); DUMPREG(r);
1140
1141# if defined(__x86_64__)
1142# define DUMPREG(r) DUMPREG64(r)
1143 DUMPREG(rax); DUMPREG(rbx); DUMPREG(rcx); DUMPREG(rdx); Printf("\n");
1144 DUMPREG(rdi); DUMPREG(rsi); DUMPREG(rbp); DUMPREG(rsp); Printf("\n");
1145 DUMPREG_(r8); DUMPREG_(r9); DUMPREG(r10); DUMPREG(r11); Printf("\n");
1146 DUMPREG(r12); DUMPREG(r13); DUMPREG(r14); DUMPREG(r15); Printf("\n");
1147# elif defined(__i386__)
1148# define DUMPREG(r) DUMPREG32(r)
1149 DUMPREG(eax); DUMPREG(ebx); DUMPREG(ecx); DUMPREG(edx); Printf("\n");
1150 DUMPREG(edi); DUMPREG(esi); DUMPREG(ebp); DUMPREG(esp); Printf("\n");
1151# elif defined(__aarch64__)
1152# define DUMPREG(r) DUMPREG64(r)
1153 DUMPREG_(x[0]); DUMPREG_(x[1]); DUMPREG_(x[2]); DUMPREG_(x[3]); Printf("\n");
1154 DUMPREG_(x[4]); DUMPREG_(x[5]); DUMPREG_(x[6]); DUMPREG_(x[7]); Printf("\n");
1155 DUMPREG_(x[8]); DUMPREG_(x[9]); DUMPREG(x[10]); DUMPREG(x[11]); Printf("\n");
1156 DUMPREG(x[12]); DUMPREG(x[13]); DUMPREG(x[14]); DUMPREG(x[15]); Printf("\n");
1157 DUMPREG(x[16]); DUMPREG(x[17]); DUMPREG(x[18]); DUMPREG(x[19]); Printf("\n");
1158 DUMPREG(x[20]); DUMPREG(x[21]); DUMPREG(x[22]); DUMPREG(x[23]); Printf("\n");
1159 DUMPREG(x[24]); DUMPREG(x[25]); DUMPREG(x[26]); DUMPREG(x[27]); Printf("\n");
1160 DUMPREG(x[28]); DUMPREGA64(fp); DUMPREGA64(lr); DUMPREGA64(sp); Printf("\n");
1161# elif defined(__arm__)
1162# define DUMPREG(r) DUMPREG32(r)
1163 DUMPREG_(r[0]); DUMPREG_(r[1]); DUMPREG_(r[2]); DUMPREG_(r[3]); Printf("\n");
1164 DUMPREG_(r[4]); DUMPREG_(r[5]); DUMPREG_(r[6]); DUMPREG_(r[7]); Printf("\n");
1165 DUMPREG_(r[8]); DUMPREG_(r[9]); DUMPREG(r[10]); DUMPREG(r[11]); Printf("\n");
1166 DUMPREG(r[12]); DUMPREG___(sp); DUMPREG___(lr); DUMPREG___(pc); Printf("\n");
1167# else
1168# error "Unknown architecture"
1169# endif
1170
1171# undef DUMPREG64
1172# undef DUMPREG32
1173# undef DUMPREG_
1174# undef DUMPREG__
1175# undef DUMPREG___
1176# undef DUMPREG
1177}
1178
1179static inline bool CompareBaseAddress(const LoadedModule &a,
1180 const LoadedModule &b) {
1181 return a.base_address() < b.base_address();
1182}
1183
1184void FormatUUID(char *out, uptr size, const u8 *uuid) {
1185 internal_snprintf(out, size,
1186 "<%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-"
1187 "%02X%02X%02X%02X%02X%02X>",
1188 uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5],
1189 uuid[6], uuid[7], uuid[8], uuid[9], uuid[10], uuid[11],
1190 uuid[12], uuid[13], uuid[14], uuid[15]);
1191}
1192
1193void PrintModuleMap() {
1194 Printf("Process module map:\n");
1195 MemoryMappingLayout memory_mapping(false);
1196 InternalMmapVector<LoadedModule> modules;
1197 modules.reserve(128);
1198 memory_mapping.DumpListOfModules(&modules);
1199 Sort(modules.data(), modules.size(), CompareBaseAddress);
1200 for (uptr i = 0; i < modules.size(); ++i) {
1201 char uuid_str[128];
1202 FormatUUID(uuid_str, sizeof(uuid_str), modules[i].uuid());
1203 Printf("0x%zx-0x%zx %s (%s) %s\n", modules[i].base_address(),
1204 modules[i].max_executable_address(), modules[i].full_name(),
1205 ModuleArchToString(modules[i].arch()), uuid_str);
1206 }
1207 Printf("End of module map.\n");
1208}
1209
1210void CheckNoDeepBind(const char *filename, int flag) {
1211 // Do nothing.
1212}
1213
1214bool GetRandom(void *buffer, uptr length, bool blocking) {
1215 if (!buffer || !length || length > 256)
1216 return false;
1217 // arc4random never fails.
1218 REAL(arc4random_buf)(buffer, length);
1219 return true;
1220}
1221
1222u32 GetNumberOfCPUs() {
1223 return (u32)sysconf(_SC_NPROCESSORS_ONLN);
1224}
1225
1226} // namespace __sanitizer
1227
1228#endif // SANITIZER_MAC
lib/tsan/sanitizer_common/sanitizer_mac.h created+84
...@@ -0,0 +1,84 @@
1//===-- sanitizer_mac.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 various sanitizers' runtime libraries and
10// provides definitions for OSX-specific functions.
11//===----------------------------------------------------------------------===//
12#ifndef SANITIZER_MAC_H
13#define SANITIZER_MAC_H
14
15#include "sanitizer_common.h"
16#include "sanitizer_platform.h"
17#if SANITIZER_MAC
18#include "sanitizer_posix.h"
19
20namespace __sanitizer {
21
22struct MemoryMappingLayoutData {
23 int current_image;
24 u32 current_magic;
25 u32 current_filetype;
26 ModuleArch current_arch;
27 u8 current_uuid[kModuleUUIDSize];
28 int current_load_cmd_count;
29 const char *current_load_cmd_addr;
30 bool current_instrumented;
31};
32
33template <typename VersionType>
34struct VersionBase {
35 u16 major;
36 u16 minor;
37
38 VersionBase(u16 major, u16 minor) : major(major), minor(minor) {}
39
40 bool operator==(const VersionType &other) const {
41 return major == other.major && minor == other.minor;
42 }
43 bool operator>=(const VersionType &other) const {
44 return major > other.major ||
45 (major == other.major && minor >= other.minor);
46 }
47};
48
49struct MacosVersion : VersionBase<MacosVersion> {
50 MacosVersion(u16 major, u16 minor) : VersionBase(major, minor) {}
51};
52
53struct DarwinKernelVersion : VersionBase<DarwinKernelVersion> {
54 DarwinKernelVersion(u16 major, u16 minor) : VersionBase(major, minor) {}
55};
56
57MacosVersion GetMacosAlignedVersion();
58DarwinKernelVersion GetDarwinKernelVersion();
59
60char **GetEnviron();
61
62void RestrictMemoryToMaxAddress(uptr max_address);
63
64} // namespace __sanitizer
65
66extern "C" {
67static char __crashreporter_info_buff__[__sanitizer::kErrorMessageBufferSize] =
68 {};
69static const char *__crashreporter_info__ __attribute__((__used__)) =
70 &__crashreporter_info_buff__[0];
71asm(".desc ___crashreporter_info__, 0x10");
72} // extern "C"
73
74namespace __sanitizer {
75static BlockingMutex crashreporter_info_mutex(LINKER_INITIALIZED);
76
77INLINE void CRAppendCrashLogMessage(const char *msg) {
78 BlockingMutexLock l(&crashreporter_info_mutex);
79 internal_strlcat(__crashreporter_info_buff__, msg,
80 sizeof(__crashreporter_info_buff__)); }
81} // namespace __sanitizer
82
83#endif // SANITIZER_MAC
84#endif // SANITIZER_MAC_H
lib/tsan/sanitizer_common/sanitizer_malloc_mac.inc created+420
...@@ -0,0 +1,420 @@
1//===-- sanitizer_malloc_mac.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 contains Mac-specific malloc interceptors and a custom zone
10// implementation, which together replace the system allocator.
11//
12//===----------------------------------------------------------------------===//
13
14#include "sanitizer_common/sanitizer_platform.h"
15#if !SANITIZER_MAC
16#error "This file should only be compiled on Darwin."
17#endif
18
19#include <AvailabilityMacros.h>
20#include <CoreFoundation/CFBase.h>
21#include <dlfcn.h>
22#include <malloc/malloc.h>
23#include <sys/mman.h>
24
25#include "interception/interception.h"
26#include "sanitizer_common/sanitizer_mac.h"
27
28// Similar code is used in Google Perftools,
29// https://github.com/gperftools/gperftools.
30
31namespace __sanitizer {
32
33extern malloc_zone_t sanitizer_zone;
34
35struct sanitizer_malloc_introspection_t : public malloc_introspection_t {
36 // IMPORTANT: Do not change the order, alignment, or types of these fields to
37 // maintain binary compatibility. You should only add fields to this struct.
38
39 // Used to track changes to the allocator that will affect
40 // zone enumeration.
41 u64 allocator_enumeration_version;
42 uptr allocator_ptr;
43 uptr allocator_size;
44};
45
46u64 GetMallocZoneAllocatorEnumerationVersion() {
47 // This represents the current allocator ABI version.
48 // This field should be incremented every time the Allocator
49 // ABI changes in a way that breaks allocator enumeration.
50 return 0;
51}
52
53} // namespace __sanitizer
54
55INTERCEPTOR(malloc_zone_t *, malloc_create_zone,
56 vm_size_t start_size, unsigned zone_flags) {
57 COMMON_MALLOC_ENTER();
58 uptr page_size = GetPageSizeCached();
59 uptr allocated_size = RoundUpTo(sizeof(sanitizer_zone), page_size);
60 COMMON_MALLOC_MEMALIGN(page_size, allocated_size);
61 malloc_zone_t *new_zone = (malloc_zone_t *)p;
62 internal_memcpy(new_zone, &sanitizer_zone, sizeof(sanitizer_zone));
63 new_zone->zone_name = NULL; // The name will be changed anyway.
64 // Prevent the client app from overwriting the zone contents.
65 // Library functions that need to modify the zone will set PROT_WRITE on it.
66 // This matches the behavior of malloc_create_zone() on OSX 10.7 and higher.
67 mprotect(new_zone, allocated_size, PROT_READ);
68 // We're explicitly *NOT* registering the zone.
69 return new_zone;
70}
71
72INTERCEPTOR(void, malloc_destroy_zone, malloc_zone_t *zone) {
73 COMMON_MALLOC_ENTER();
74 // We don't need to do anything here. We're not registering new zones, so we
75 // don't to unregister. Just un-mprotect and free() the zone.
76 uptr page_size = GetPageSizeCached();
77 uptr allocated_size = RoundUpTo(sizeof(sanitizer_zone), page_size);
78 mprotect(zone, allocated_size, PROT_READ | PROT_WRITE);
79 if (zone->zone_name) {
80 COMMON_MALLOC_FREE((void *)zone->zone_name);
81 }
82 COMMON_MALLOC_FREE(zone);
83}
84
85INTERCEPTOR(malloc_zone_t *, malloc_default_zone, void) {
86 COMMON_MALLOC_ENTER();
87 return &sanitizer_zone;
88}
89
90INTERCEPTOR(malloc_zone_t *, malloc_zone_from_ptr, const void *ptr) {
91 COMMON_MALLOC_ENTER();
92 size_t size = sanitizer_zone.size(&sanitizer_zone, ptr);
93 if (size) { // Claimed by sanitizer zone?
94 return &sanitizer_zone;
95 }
96 return REAL(malloc_zone_from_ptr)(ptr);
97}
98
99INTERCEPTOR(malloc_zone_t *, malloc_default_purgeable_zone, void) {
100 // FIXME: ASan should support purgeable allocations.
101 // https://github.com/google/sanitizers/issues/139
102 COMMON_MALLOC_ENTER();
103 return &sanitizer_zone;
104}
105
106INTERCEPTOR(void, malloc_make_purgeable, void *ptr) {
107 // FIXME: ASan should support purgeable allocations. Ignoring them is fine
108 // for now.
109 COMMON_MALLOC_ENTER();
110}
111
112INTERCEPTOR(int, malloc_make_nonpurgeable, void *ptr) {
113 // FIXME: ASan should support purgeable allocations. Ignoring them is fine
114 // for now.
115 COMMON_MALLOC_ENTER();
116 // Must return 0 if the contents were not purged since the last call to
117 // malloc_make_purgeable().
118 return 0;
119}
120
121INTERCEPTOR(void, malloc_set_zone_name, malloc_zone_t *zone, const char *name) {
122 COMMON_MALLOC_ENTER();
123 // Allocate |sizeof(COMMON_MALLOC_ZONE_NAME "-") + internal_strlen(name)|
124 // bytes.
125 size_t buflen =
126 sizeof(COMMON_MALLOC_ZONE_NAME "-") + (name ? internal_strlen(name) : 0);
127 InternalScopedString new_name(buflen);
128 if (name && zone->introspect == sanitizer_zone.introspect) {
129 new_name.append(COMMON_MALLOC_ZONE_NAME "-%s", name);
130 name = new_name.data();
131 }
132
133 // Call the system malloc's implementation for both external and our zones,
134 // since that appropriately changes VM region protections on the zone.
135 REAL(malloc_set_zone_name)(zone, name);
136}
137
138INTERCEPTOR(void *, malloc, size_t size) {
139 COMMON_MALLOC_ENTER();
140 COMMON_MALLOC_MALLOC(size);
141 return p;
142}
143
144INTERCEPTOR(void, free, void *ptr) {
145 COMMON_MALLOC_ENTER();
146 if (!ptr) return;
147 COMMON_MALLOC_FREE(ptr);
148}
149
150INTERCEPTOR(void *, realloc, void *ptr, size_t size) {
151 COMMON_MALLOC_ENTER();
152 COMMON_MALLOC_REALLOC(ptr, size);
153 return p;
154}
155
156INTERCEPTOR(void *, calloc, size_t nmemb, size_t size) {
157 COMMON_MALLOC_ENTER();
158 COMMON_MALLOC_CALLOC(nmemb, size);
159 return p;
160}
161
162INTERCEPTOR(void *, valloc, size_t size) {
163 COMMON_MALLOC_ENTER();
164 COMMON_MALLOC_VALLOC(size);
165 return p;
166}
167
168INTERCEPTOR(size_t, malloc_good_size, size_t size) {
169 COMMON_MALLOC_ENTER();
170 return sanitizer_zone.introspect->good_size(&sanitizer_zone, size);
171}
172
173INTERCEPTOR(int, posix_memalign, void **memptr, size_t alignment, size_t size) {
174 COMMON_MALLOC_ENTER();
175 CHECK(memptr);
176 COMMON_MALLOC_POSIX_MEMALIGN(memptr, alignment, size);
177 return res;
178}
179
180namespace {
181
182// TODO(glider): the __sanitizer_mz_* functions should be united with the Linux
183// wrappers, as they are basically copied from there.
184extern "C"
185SANITIZER_INTERFACE_ATTRIBUTE
186size_t __sanitizer_mz_size(malloc_zone_t* zone, const void* ptr) {
187 COMMON_MALLOC_SIZE(ptr);
188 return size;
189}
190
191extern "C"
192SANITIZER_INTERFACE_ATTRIBUTE
193void *__sanitizer_mz_malloc(malloc_zone_t *zone, uptr size) {
194 COMMON_MALLOC_ENTER();
195 COMMON_MALLOC_MALLOC(size);
196 return p;
197}
198
199extern "C"
200SANITIZER_INTERFACE_ATTRIBUTE
201void *__sanitizer_mz_calloc(malloc_zone_t *zone, size_t nmemb, size_t size) {
202 if (UNLIKELY(!COMMON_MALLOC_SANITIZER_INITIALIZED)) {
203 // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
204 const size_t kCallocPoolSize = 1024;
205 static uptr calloc_memory_for_dlsym[kCallocPoolSize];
206 static size_t allocated;
207 size_t size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize;
208 void *mem = (void*)&calloc_memory_for_dlsym[allocated];
209 allocated += size_in_words;
210 CHECK(allocated < kCallocPoolSize);
211 return mem;
212 }
213 COMMON_MALLOC_CALLOC(nmemb, size);
214 return p;
215}
216
217extern "C"
218SANITIZER_INTERFACE_ATTRIBUTE
219void *__sanitizer_mz_valloc(malloc_zone_t *zone, size_t size) {
220 COMMON_MALLOC_ENTER();
221 COMMON_MALLOC_VALLOC(size);
222 return p;
223}
224
225// TODO(glider): the allocation callbacks need to be refactored.
226extern "C"
227SANITIZER_INTERFACE_ATTRIBUTE
228void __sanitizer_mz_free(malloc_zone_t *zone, void *ptr) {
229 if (!ptr) return;
230 COMMON_MALLOC_FREE(ptr);
231}
232
233#define GET_ZONE_FOR_PTR(ptr) \
234 malloc_zone_t *zone_ptr = WRAP(malloc_zone_from_ptr)(ptr); \
235 const char *zone_name = (zone_ptr == 0) ? 0 : zone_ptr->zone_name
236
237extern "C"
238SANITIZER_INTERFACE_ATTRIBUTE
239void *__sanitizer_mz_realloc(malloc_zone_t *zone, void *ptr, size_t new_size) {
240 if (!ptr) {
241 COMMON_MALLOC_MALLOC(new_size);
242 return p;
243 } else {
244 COMMON_MALLOC_SIZE(ptr);
245 if (size) {
246 COMMON_MALLOC_REALLOC(ptr, new_size);
247 return p;
248 } else {
249 // We can't recover from reallocating an unknown address, because
250 // this would require reading at most |new_size| bytes from
251 // potentially unaccessible memory.
252 GET_ZONE_FOR_PTR(ptr);
253 COMMON_MALLOC_REPORT_UNKNOWN_REALLOC(ptr, zone_ptr, zone_name);
254 return nullptr;
255 }
256 }
257}
258
259extern "C"
260SANITIZER_INTERFACE_ATTRIBUTE
261void __sanitizer_mz_destroy(malloc_zone_t* zone) {
262 // A no-op -- we will not be destroyed!
263 Report("__sanitizer_mz_destroy() called -- ignoring\n");
264}
265
266extern "C"
267SANITIZER_INTERFACE_ATTRIBUTE
268void *__sanitizer_mz_memalign(malloc_zone_t *zone, size_t align, size_t size) {
269 COMMON_MALLOC_ENTER();
270 COMMON_MALLOC_MEMALIGN(align, size);
271 return p;
272}
273
274// This public API exists purely for testing purposes.
275extern "C"
276SANITIZER_INTERFACE_ATTRIBUTE
277malloc_zone_t* __sanitizer_mz_default_zone() {
278 return &sanitizer_zone;
279}
280
281// This function is currently unused, and we build with -Werror.
282#if 0
283void __sanitizer_mz_free_definite_size(
284 malloc_zone_t* zone, void *ptr, size_t size) {
285 // TODO(glider): check that |size| is valid.
286 UNIMPLEMENTED();
287}
288#endif
289
290#ifndef COMMON_MALLOC_HAS_ZONE_ENUMERATOR
291#error "COMMON_MALLOC_HAS_ZONE_ENUMERATOR must be defined"
292#endif
293static_assert((COMMON_MALLOC_HAS_ZONE_ENUMERATOR) == 0 ||
294 (COMMON_MALLOC_HAS_ZONE_ENUMERATOR) == 1,
295 "COMMON_MALLOC_HAS_ZONE_ENUMERATOR must be 0 or 1");
296
297#if COMMON_MALLOC_HAS_ZONE_ENUMERATOR
298// Forward declare and expect the implementation to provided by
299// includer.
300kern_return_t mi_enumerator(task_t task, void *, unsigned type_mask,
301 vm_address_t zone_address, memory_reader_t reader,
302 vm_range_recorder_t recorder);
303#else
304// Provide stub implementation that fails.
305kern_return_t mi_enumerator(task_t task, void *, unsigned type_mask,
306 vm_address_t zone_address, memory_reader_t reader,
307 vm_range_recorder_t recorder) {
308 // Not supported.
309 return KERN_FAILURE;
310}
311#endif
312
313#ifndef COMMON_MALLOC_HAS_EXTRA_INTROSPECTION_INIT
314#error "COMMON_MALLOC_HAS_EXTRA_INTROSPECTION_INIT must be defined"
315#endif
316static_assert((COMMON_MALLOC_HAS_EXTRA_INTROSPECTION_INIT) == 0 ||
317 (COMMON_MALLOC_HAS_EXTRA_INTROSPECTION_INIT) == 1,
318 "COMMON_MALLOC_HAS_EXTRA_INTROSPECTION_INIT must be 0 or 1");
319#if COMMON_MALLOC_HAS_EXTRA_INTROSPECTION_INIT
320// Forward declare and expect the implementation to provided by
321// includer.
322void mi_extra_init(
323 sanitizer_malloc_introspection_t *mi);
324#else
325void mi_extra_init(
326 sanitizer_malloc_introspection_t *mi) {
327 // Just zero initialize the fields.
328 mi->allocator_ptr = 0;
329 mi->allocator_size = 0;
330}
331#endif
332
333size_t mi_good_size(malloc_zone_t *zone, size_t size) {
334 // I think it's always safe to return size, but we maybe could do better.
335 return size;
336}
337
338boolean_t mi_check(malloc_zone_t *zone) {
339 UNIMPLEMENTED();
340}
341
342void mi_print(malloc_zone_t *zone, boolean_t verbose) {
343 UNIMPLEMENTED();
344}
345
346void mi_log(malloc_zone_t *zone, void *address) {
347 // I don't think we support anything like this
348}
349
350void mi_force_lock(malloc_zone_t *zone) {
351 COMMON_MALLOC_FORCE_LOCK();
352}
353
354void mi_force_unlock(malloc_zone_t *zone) {
355 COMMON_MALLOC_FORCE_UNLOCK();
356}
357
358void mi_statistics(malloc_zone_t *zone, malloc_statistics_t *stats) {
359 COMMON_MALLOC_FILL_STATS(zone, stats);
360}
361
362boolean_t mi_zone_locked(malloc_zone_t *zone) {
363 // UNIMPLEMENTED();
364 return false;
365}
366
367} // unnamed namespace
368
369namespace COMMON_MALLOC_NAMESPACE {
370
371void InitMallocZoneFields() {
372 static sanitizer_malloc_introspection_t sanitizer_zone_introspection;
373 // Ok to use internal_memset, these places are not performance-critical.
374 internal_memset(&sanitizer_zone_introspection, 0,
375 sizeof(sanitizer_zone_introspection));
376
377 sanitizer_zone_introspection.enumerator = &mi_enumerator;
378 sanitizer_zone_introspection.good_size = &mi_good_size;
379 sanitizer_zone_introspection.check = &mi_check;
380 sanitizer_zone_introspection.print = &mi_print;
381 sanitizer_zone_introspection.log = &mi_log;
382 sanitizer_zone_introspection.force_lock = &mi_force_lock;
383 sanitizer_zone_introspection.force_unlock = &mi_force_unlock;
384 sanitizer_zone_introspection.statistics = &mi_statistics;
385 sanitizer_zone_introspection.zone_locked = &mi_zone_locked;
386
387 // Set current allocator enumeration version.
388 sanitizer_zone_introspection.allocator_enumeration_version =
389 GetMallocZoneAllocatorEnumerationVersion();
390
391 // Perform any sanitizer specific initialization.
392 mi_extra_init(&sanitizer_zone_introspection);
393
394 internal_memset(&sanitizer_zone, 0, sizeof(malloc_zone_t));
395
396 // Use version 6 for OSX >= 10.6.
397 sanitizer_zone.version = 6;
398 sanitizer_zone.zone_name = COMMON_MALLOC_ZONE_NAME;
399 sanitizer_zone.size = &__sanitizer_mz_size;
400 sanitizer_zone.malloc = &__sanitizer_mz_malloc;
401 sanitizer_zone.calloc = &__sanitizer_mz_calloc;
402 sanitizer_zone.valloc = &__sanitizer_mz_valloc;
403 sanitizer_zone.free = &__sanitizer_mz_free;
404 sanitizer_zone.realloc = &__sanitizer_mz_realloc;
405 sanitizer_zone.destroy = &__sanitizer_mz_destroy;
406 sanitizer_zone.batch_malloc = 0;
407 sanitizer_zone.batch_free = 0;
408 sanitizer_zone.free_definite_size = 0;
409 sanitizer_zone.memalign = &__sanitizer_mz_memalign;
410 sanitizer_zone.introspect = &sanitizer_zone_introspection;
411}
412
413void ReplaceSystemMalloc() {
414 InitMallocZoneFields();
415
416 // Register the zone.
417 malloc_zone_register(&sanitizer_zone);
418}
419
420} // namespace COMMON_MALLOC_NAMESPACE
lib/tsan/sanitizer_common/sanitizer_mutex.h created+223
...@@ -0,0 +1,223 @@
1//===-- sanitizer_mutex.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/AddressSanitizer runtime.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef SANITIZER_MUTEX_H
14#define SANITIZER_MUTEX_H
15
16#include "sanitizer_atomic.h"
17#include "sanitizer_internal_defs.h"
18#include "sanitizer_libc.h"
19
20namespace __sanitizer {
21
22class StaticSpinMutex {
23 public:
24 void Init() {
25 atomic_store(&state_, 0, memory_order_relaxed);
26 }
27
28 void Lock() {
29 if (TryLock())
30 return;
31 LockSlow();
32 }
33
34 bool TryLock() {
35 return atomic_exchange(&state_, 1, memory_order_acquire) == 0;
36 }
37
38 void Unlock() {
39 atomic_store(&state_, 0, memory_order_release);
40 }
41
42 void CheckLocked() {
43 CHECK_EQ(atomic_load(&state_, memory_order_relaxed), 1);
44 }
45
46 private:
47 atomic_uint8_t state_;
48
49 void NOINLINE LockSlow() {
50 for (int i = 0;; i++) {
51 if (i < 10)
52 proc_yield(10);
53 else
54 internal_sched_yield();
55 if (atomic_load(&state_, memory_order_relaxed) == 0
56 && atomic_exchange(&state_, 1, memory_order_acquire) == 0)
57 return;
58 }
59 }
60};
61
62class SpinMutex : public StaticSpinMutex {
63 public:
64 SpinMutex() {
65 Init();
66 }
67
68 private:
69 SpinMutex(const SpinMutex&);
70 void operator=(const SpinMutex&);
71};
72
73class BlockingMutex {
74 public:
75 explicit constexpr BlockingMutex(LinkerInitialized)
76 : opaque_storage_ {0, }, owner_ {0} {}
77 BlockingMutex();
78 void Lock();
79 void Unlock();
80
81 // This function does not guarantee an explicit check that the calling thread
82 // is the thread which owns the mutex. This behavior, while more strictly
83 // correct, causes problems in cases like StopTheWorld, where a parent thread
84 // owns the mutex but a child checks that it is locked. Rather than
85 // maintaining complex state to work around those situations, the check only
86 // checks that the mutex is owned, and assumes callers to be generally
87 // well-behaved.
88 void CheckLocked();
89
90 private:
91 // Solaris mutex_t has a member that requires 64-bit alignment.
92 ALIGNED(8) uptr opaque_storage_[10];
93 uptr owner_; // for debugging
94};
95
96// Reader-writer spin mutex.
97class RWMutex {
98 public:
99 RWMutex() {
100 atomic_store(&state_, kUnlocked, memory_order_relaxed);
101 }
102
103 ~RWMutex() {
104 CHECK_EQ(atomic_load(&state_, memory_order_relaxed), kUnlocked);
105 }
106
107 void Lock() {
108 u32 cmp = kUnlocked;
109 if (atomic_compare_exchange_strong(&state_, &cmp, kWriteLock,
110 memory_order_acquire))
111 return;
112 LockSlow();
113 }
114
115 void Unlock() {
116 u32 prev = atomic_fetch_sub(&state_, kWriteLock, memory_order_release);
117 DCHECK_NE(prev & kWriteLock, 0);
118 (void)prev;
119 }
120
121 void ReadLock() {
122 u32 prev = atomic_fetch_add(&state_, kReadLock, memory_order_acquire);
123 if ((prev & kWriteLock) == 0)
124 return;
125 ReadLockSlow();
126 }
127
128 void ReadUnlock() {
129 u32 prev = atomic_fetch_sub(&state_, kReadLock, memory_order_release);
130 DCHECK_EQ(prev & kWriteLock, 0);
131 DCHECK_GT(prev & ~kWriteLock, 0);
132 (void)prev;
133 }
134
135 void CheckLocked() {
136 CHECK_NE(atomic_load(&state_, memory_order_relaxed), kUnlocked);
137 }
138
139 private:
140 atomic_uint32_t state_;
141
142 enum {
143 kUnlocked = 0,
144 kWriteLock = 1,
145 kReadLock = 2
146 };
147
148 void NOINLINE LockSlow() {
149 for (int i = 0;; i++) {
150 if (i < 10)
151 proc_yield(10);
152 else
153 internal_sched_yield();
154 u32 cmp = atomic_load(&state_, memory_order_relaxed);
155 if (cmp == kUnlocked &&
156 atomic_compare_exchange_weak(&state_, &cmp, kWriteLock,
157 memory_order_acquire))
158 return;
159 }
160 }
161
162 void NOINLINE ReadLockSlow() {
163 for (int i = 0;; i++) {
164 if (i < 10)
165 proc_yield(10);
166 else
167 internal_sched_yield();
168 u32 prev = atomic_load(&state_, memory_order_acquire);
169 if ((prev & kWriteLock) == 0)
170 return;
171 }
172 }
173
174 RWMutex(const RWMutex&);
175 void operator = (const RWMutex&);
176};
177
178template<typename MutexType>
179class GenericScopedLock {
180 public:
181 explicit GenericScopedLock(MutexType *mu)
182 : mu_(mu) {
183 mu_->Lock();
184 }
185
186 ~GenericScopedLock() {
187 mu_->Unlock();
188 }
189
190 private:
191 MutexType *mu_;
192
193 GenericScopedLock(const GenericScopedLock&);
194 void operator=(const GenericScopedLock&);
195};
196
197template<typename MutexType>
198class GenericScopedReadLock {
199 public:
200 explicit GenericScopedReadLock(MutexType *mu)
201 : mu_(mu) {
202 mu_->ReadLock();
203 }
204
205 ~GenericScopedReadLock() {
206 mu_->ReadUnlock();
207 }
208
209 private:
210 MutexType *mu_;
211
212 GenericScopedReadLock(const GenericScopedReadLock&);
213 void operator=(const GenericScopedReadLock&);
214};
215
216typedef GenericScopedLock<StaticSpinMutex> SpinMutexLock;
217typedef GenericScopedLock<BlockingMutex> BlockingMutexLock;
218typedef GenericScopedLock<RWMutex> RWMutexLock;
219typedef GenericScopedReadLock<RWMutex> RWMutexReadLock;
220
221} // namespace __sanitizer
222
223#endif // SANITIZER_MUTEX_H
lib/tsan/sanitizer_common/sanitizer_netbsd.cpp created+343
...@@ -0,0 +1,343 @@
1//===-- sanitizer_netbsd.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 shared between Sanitizer run-time libraries and implements
10// NetBSD-specific functions from sanitizer_libc.h.
11//===----------------------------------------------------------------------===//
12
13#include "sanitizer_platform.h"
14
15#if SANITIZER_NETBSD
16
17#include "sanitizer_common.h"
18#include "sanitizer_flags.h"
19#include "sanitizer_getauxval.h"
20#include "sanitizer_internal_defs.h"
21#include "sanitizer_libc.h"
22#include "sanitizer_linux.h"
23#include "sanitizer_mutex.h"
24#include "sanitizer_placement_new.h"
25#include "sanitizer_procmaps.h"
26
27#include <sys/param.h>
28#include <sys/types.h>
29
30#include <sys/exec.h>
31#include <sys/mman.h>
32#include <sys/ptrace.h>
33#include <sys/resource.h>
34#include <sys/stat.h>
35#include <sys/syscall.h>
36#include <sys/sysctl.h>
37#include <sys/time.h>
38
39#include <dlfcn.h>
40#include <errno.h>
41#include <fcntl.h>
42#include <limits.h>
43#include <link.h>
44#include <lwp.h>
45#include <pthread.h>
46#include <sched.h>
47#include <signal.h>
48#include <ucontext.h>
49#include <unistd.h>
50
51extern "C" void *__mmap(void *, size_t, int, int, int, int,
52 off_t) SANITIZER_WEAK_ATTRIBUTE;
53extern "C" int __sysctl(const int *, unsigned int, void *, size_t *,
54 const void *, size_t) SANITIZER_WEAK_ATTRIBUTE;
55extern "C" int _sys_close(int) SANITIZER_WEAK_ATTRIBUTE;
56extern "C" int _sys_open(const char *, int, ...) SANITIZER_WEAK_ATTRIBUTE;
57extern "C" ssize_t _sys_read(int, void *, size_t) SANITIZER_WEAK_ATTRIBUTE;
58extern "C" ssize_t _sys_write(int, const void *,
59 size_t) SANITIZER_WEAK_ATTRIBUTE;
60extern "C" int __ftruncate(int, int, off_t) SANITIZER_WEAK_ATTRIBUTE;
61extern "C" ssize_t _sys_readlink(const char *, char *,
62 size_t) SANITIZER_WEAK_ATTRIBUTE;
63extern "C" int _sys_sched_yield() SANITIZER_WEAK_ATTRIBUTE;
64extern "C" int _sys___nanosleep50(const void *,
65 void *) SANITIZER_WEAK_ATTRIBUTE;
66extern "C" int _sys_execve(const char *, char *const[],
67 char *const[]) SANITIZER_WEAK_ATTRIBUTE;
68extern "C" off_t __lseek(int, int, off_t, int) SANITIZER_WEAK_ATTRIBUTE;
69extern "C" int __fork() SANITIZER_WEAK_ATTRIBUTE;
70extern "C" int _sys___sigprocmask14(int, const void *,
71 void *) SANITIZER_WEAK_ATTRIBUTE;
72extern "C" int _sys___wait450(int wpid, int *, int,
73 void *) SANITIZER_WEAK_ATTRIBUTE;
74
75namespace __sanitizer {
76
77static void *GetRealLibcAddress(const char *symbol) {
78 void *real = dlsym(RTLD_NEXT, symbol);
79 if (!real)
80 real = dlsym(RTLD_DEFAULT, symbol);
81 if (!real) {
82 Printf("GetRealLibcAddress failed for symbol=%s", symbol);
83 Die();
84 }
85 return real;
86}
87
88#define _REAL(func, ...) real##_##func(__VA_ARGS__)
89#define DEFINE__REAL(ret_type, func, ...) \
90 static ret_type (*real_##func)(__VA_ARGS__) = NULL; \
91 if (!real_##func) { \
92 real_##func = (ret_type(*)(__VA_ARGS__))GetRealLibcAddress(#func); \
93 } \
94 CHECK(real_##func);
95
96// --------------- sanitizer_libc.h
97uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd,
98 u64 offset) {
99 CHECK(&__mmap);
100 return (uptr)__mmap(addr, length, prot, flags, fd, 0, offset);
101}
102
103uptr internal_munmap(void *addr, uptr length) {
104 DEFINE__REAL(int, munmap, void *a, uptr b);
105 return _REAL(munmap, addr, length);
106}
107
108int internal_mprotect(void *addr, uptr length, int prot) {
109 DEFINE__REAL(int, mprotect, void *a, uptr b, int c);
110 return _REAL(mprotect, addr, length, prot);
111}
112
113uptr internal_close(fd_t fd) {
114 CHECK(&_sys_close);
115 return _sys_close(fd);
116}
117
118uptr internal_open(const char *filename, int flags) {
119 CHECK(&_sys_open);
120 return _sys_open(filename, flags);
121}
122
123uptr internal_open(const char *filename, int flags, u32 mode) {
124 CHECK(&_sys_open);
125 return _sys_open(filename, flags, mode);
126}
127
128uptr internal_read(fd_t fd, void *buf, uptr count) {
129 sptr res;
130 CHECK(&_sys_read);
131 HANDLE_EINTR(res, (sptr)_sys_read(fd, buf, (size_t)count));
132 return res;
133}
134
135uptr internal_write(fd_t fd, const void *buf, uptr count) {
136 sptr res;
137 CHECK(&_sys_write);
138 HANDLE_EINTR(res, (sptr)_sys_write(fd, buf, count));
139 return res;
140}
141
142uptr internal_ftruncate(fd_t fd, uptr size) {
143 sptr res;
144 CHECK(&__ftruncate);
145 HANDLE_EINTR(res, __ftruncate(fd, 0, (s64)size));
146 return res;
147}
148
149uptr internal_stat(const char *path, void *buf) {
150 DEFINE__REAL(int, __stat50, const char *a, void *b);
151 return _REAL(__stat50, path, buf);
152}
153
154uptr internal_lstat(const char *path, void *buf) {
155 DEFINE__REAL(int, __lstat50, const char *a, void *b);
156 return _REAL(__lstat50, path, buf);
157}
158
159uptr internal_fstat(fd_t fd, void *buf) {
160 DEFINE__REAL(int, __fstat50, int a, void *b);
161 return _REAL(__fstat50, fd, buf);
162}
163
164uptr internal_filesize(fd_t fd) {
165 struct stat st;
166 if (internal_fstat(fd, &st))
167 return -1;
168 return (uptr)st.st_size;
169}
170
171uptr internal_dup(int oldfd) {
172 DEFINE__REAL(int, dup, int a);
173 return _REAL(dup, oldfd);
174}
175
176uptr internal_dup2(int oldfd, int newfd) {
177 DEFINE__REAL(int, dup2, int a, int b);
178 return _REAL(dup2, oldfd, newfd);
179}
180
181uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
182 CHECK(&_sys_readlink);
183 return (uptr)_sys_readlink(path, buf, bufsize);
184}
185
186uptr internal_unlink(const char *path) {
187 DEFINE__REAL(int, unlink, const char *a);
188 return _REAL(unlink, path);
189}
190
191uptr internal_rename(const char *oldpath, const char *newpath) {
192 DEFINE__REAL(int, rename, const char *a, const char *b);
193 return _REAL(rename, oldpath, newpath);
194}
195
196uptr internal_sched_yield() {
197 CHECK(&_sys_sched_yield);
198 return _sys_sched_yield();
199}
200
201void internal__exit(int exitcode) {
202 DEFINE__REAL(void, _exit, int a);
203 _REAL(_exit, exitcode);
204 Die(); // Unreachable.
205}
206
207unsigned int internal_sleep(unsigned int seconds) {
208 struct timespec ts;
209 ts.tv_sec = seconds;
210 ts.tv_nsec = 0;
211 CHECK(&_sys___nanosleep50);
212 int res = _sys___nanosleep50(&ts, &ts);
213 if (res)
214 return ts.tv_sec;
215 return 0;
216}
217
218uptr internal_execve(const char *filename, char *const argv[],
219 char *const envp[]) {
220 CHECK(&_sys_execve);
221 return _sys_execve(filename, argv, envp);
222}
223
224tid_t GetTid() {
225 DEFINE__REAL(int, _lwp_self);
226 return _REAL(_lwp_self);
227}
228
229int TgKill(pid_t pid, tid_t tid, int sig) {
230 DEFINE__REAL(int, _lwp_kill, int a, int b);
231 (void)pid;
232 return _REAL(_lwp_kill, tid, sig);
233}
234
235u64 NanoTime() {
236 timeval tv;
237 DEFINE__REAL(int, __gettimeofday50, void *a, void *b);
238 internal_memset(&tv, 0, sizeof(tv));
239 _REAL(__gettimeofday50, &tv, 0);
240 return (u64)tv.tv_sec * 1000 * 1000 * 1000 + tv.tv_usec * 1000;
241}
242
243uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp) {
244 DEFINE__REAL(int, __clock_gettime50, __sanitizer_clockid_t a, void *b);
245 return _REAL(__clock_gettime50, clk_id, tp);
246}
247
248uptr internal_ptrace(int request, int pid, void *addr, int data) {
249 DEFINE__REAL(int, ptrace, int a, int b, void *c, int d);
250 return _REAL(ptrace, request, pid, addr, data);
251}
252
253uptr internal_waitpid(int pid, int *status, int options) {
254 CHECK(&_sys___wait450);
255 return _sys___wait450(pid, status, options, 0 /* rusage */);
256}
257
258uptr internal_getpid() {
259 DEFINE__REAL(int, getpid);
260 return _REAL(getpid);
261}
262
263uptr internal_getppid() {
264 DEFINE__REAL(int, getppid);
265 return _REAL(getppid);
266}
267
268int internal_dlinfo(void *handle, int request, void *p) {
269 DEFINE__REAL(int, dlinfo, void *a, int b, void *c);
270 return _REAL(dlinfo, handle, request, p);
271}
272
273uptr internal_getdents(fd_t fd, void *dirp, unsigned int count) {
274 DEFINE__REAL(int, __getdents30, int a, void *b, size_t c);
275 return _REAL(__getdents30, fd, dirp, count);
276}
277
278uptr internal_lseek(fd_t fd, OFF_T offset, int whence) {
279 CHECK(&__lseek);
280 return __lseek(fd, 0, offset, whence);
281}
282
283uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) {
284 Printf("internal_prctl not implemented for NetBSD");
285 Die();
286 return 0;
287}
288
289uptr internal_sigaltstack(const void *ss, void *oss) {
290 DEFINE__REAL(int, __sigaltstack14, const void *a, void *b);
291 return _REAL(__sigaltstack14, ss, oss);
292}
293
294int internal_fork() {
295 CHECK(&__fork);
296 return __fork();
297}
298
299int internal_sysctl(const int *name, unsigned int namelen, void *oldp,
300 uptr *oldlenp, const void *newp, uptr newlen) {
301 CHECK(&__sysctl);
302 return __sysctl(name, namelen, oldp, (size_t *)oldlenp, newp, (size_t)newlen);
303}
304
305int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp,
306 const void *newp, uptr newlen) {
307 DEFINE__REAL(int, sysctlbyname, const char *a, void *b, size_t *c,
308 const void *d, size_t e);
309 return _REAL(sysctlbyname, sname, oldp, (size_t *)oldlenp, newp,
310 (size_t)newlen);
311}
312
313uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set,
314 __sanitizer_sigset_t *oldset) {
315 CHECK(&_sys___sigprocmask14);
316 return _sys___sigprocmask14(how, set, oldset);
317}
318
319void internal_sigfillset(__sanitizer_sigset_t *set) {
320 DEFINE__REAL(int, __sigfillset14, const void *a);
321 (void)_REAL(__sigfillset14, set);
322}
323
324void internal_sigemptyset(__sanitizer_sigset_t *set) {
325 DEFINE__REAL(int, __sigemptyset14, const void *a);
326 (void)_REAL(__sigemptyset14, set);
327}
328
329void internal_sigdelset(__sanitizer_sigset_t *set, int signo) {
330 DEFINE__REAL(int, __sigdelset14, const void *a, int b);
331 (void)_REAL(__sigdelset14, set, signo);
332}
333
334uptr internal_clone(int (*fn)(void *), void *child_stack, int flags,
335 void *arg) {
336 DEFINE__REAL(int, clone, int (*a)(void *b), void *c, int d, void *e);
337
338 return _REAL(clone, fn, child_stack, flags, arg);
339}
340
341} // namespace __sanitizer
342
343#endif
lib/tsan/sanitizer_common/sanitizer_openbsd.cpp created+115
...@@ -0,0 +1,115 @@
1//===-- sanitizer_openbsd.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 shared between various sanitizers' runtime libraries and
10// implements Solaris-specific functions.
11//===----------------------------------------------------------------------===//
12
13#include "sanitizer_platform.h"
14#if SANITIZER_OPENBSD
15
16#include <stdio.h>
17
18#include "sanitizer_common.h"
19#include "sanitizer_flags.h"
20#include "sanitizer_internal_defs.h"
21#include "sanitizer_libc.h"
22#include "sanitizer_placement_new.h"
23#include "sanitizer_platform_limits_posix.h"
24#include "sanitizer_procmaps.h"
25
26#include <errno.h>
27#include <fcntl.h>
28#include <limits.h>
29#include <pthread.h>
30#include <sched.h>
31#include <signal.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <sys/mman.h>
35#include <sys/shm.h>
36#include <sys/sysctl.h>
37#include <sys/types.h>
38#include <unistd.h>
39
40extern char **environ;
41
42namespace __sanitizer {
43
44uptr internal_mmap(void *addr, size_t length, int prot, int flags, int fd,
45 u64 offset) {
46 return (uptr)mmap(addr, length, prot, flags, fd, offset);
47}
48
49uptr internal_munmap(void *addr, uptr length) { return munmap(addr, length); }
50
51int internal_mprotect(void *addr, uptr length, int prot) {
52 return mprotect(addr, length, prot);
53}
54
55int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp,
56 const void *newp, uptr newlen) {
57 Printf("internal_sysctlbyname not implemented for OpenBSD");
58 Die();
59 return 0;
60}
61
62uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
63 // On OpenBSD we cannot get the full path
64 struct kinfo_proc kp;
65 uptr kl;
66 const int Mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()};
67 if (internal_sysctl(Mib, ARRAY_SIZE(Mib), &kp, &kl, NULL, 0) != -1)
68 return internal_snprintf(buf,
69 (KI_MAXCOMLEN < buf_len ? KI_MAXCOMLEN : buf_len),
70 "%s", kp.p_comm);
71 return (uptr)0;
72}
73
74static void GetArgsAndEnv(char ***argv, char ***envp) {
75 uptr nargv;
76 uptr nenv;
77 int argvmib[4] = {CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ARGV};
78 int envmib[4] = {CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ENV};
79 if (internal_sysctl(argvmib, 4, NULL, &nargv, NULL, 0) == -1) {
80 Printf("sysctl KERN_PROC_NARGV failed\n");
81 Die();
82 }
83 if (internal_sysctl(envmib, 4, NULL, &nenv, NULL, 0) == -1) {
84 Printf("sysctl KERN_PROC_NENV failed\n");
85 Die();
86 }
87 if (internal_sysctl(argvmib, 4, &argv, &nargv, NULL, 0) == -1) {
88 Printf("sysctl KERN_PROC_ARGV failed\n");
89 Die();
90 }
91 if (internal_sysctl(envmib, 4, &envp, &nenv, NULL, 0) == -1) {
92 Printf("sysctl KERN_PROC_ENV failed\n");
93 Die();
94 }
95}
96
97char **GetArgv() {
98 char **argv, **envp;
99 GetArgsAndEnv(&argv, &envp);
100 return argv;
101}
102
103char **GetEnviron() {
104 char **argv, **envp;
105 GetArgsAndEnv(&argv, &envp);
106 return envp;
107}
108
109void ReExec() {
110 UNIMPLEMENTED();
111}
112
113} // namespace __sanitizer
114
115#endif // SANITIZER_OPENBSD
lib/tsan/sanitizer_common/sanitizer_persistent_allocator.cpp created+18
...@@ -0,0 +1,18 @@
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 created+71
...@@ -0,0 +1,71 @@
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_placement_new.h created+24
...@@ -0,0 +1,24 @@
1//===-- sanitizer_placement_new.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 AddressSanitizer and ThreadSanitizer
10// run-time libraries.
11//
12// The file provides 'placement new'.
13// Do not include it into header files, only into source files.
14//===----------------------------------------------------------------------===//
15#ifndef SANITIZER_PLACEMENT_NEW_H
16#define SANITIZER_PLACEMENT_NEW_H
17
18#include "sanitizer_internal_defs.h"
19
20inline void *operator new(__sanitizer::operator_new_size_type sz, void *p) {
21 return p;
22}
23
24#endif // SANITIZER_PLACEMENT_NEW_H
lib/tsan/sanitizer_common/sanitizer_platform.h created+364
...@@ -0,0 +1,364 @@
1//===-- sanitizer_platform.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// Common platform macros.
10//===----------------------------------------------------------------------===//
11
12#ifndef SANITIZER_PLATFORM_H
13#define SANITIZER_PLATFORM_H
14
15#if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && \
16 !defined(__OpenBSD__) && !defined(__APPLE__) && !defined(_WIN32) && \
17 !defined(__Fuchsia__) && !defined(__rtems__) && \
18 !(defined(__sun__) && defined(__svr4__))
19# error "This operating system is not supported"
20#endif
21
22#if defined(__linux__)
23# define SANITIZER_LINUX 1
24#else
25# define SANITIZER_LINUX 0
26#endif
27
28#if defined(__FreeBSD__)
29# define SANITIZER_FREEBSD 1
30#else
31# define SANITIZER_FREEBSD 0
32#endif
33
34#if defined(__NetBSD__)
35# define SANITIZER_NETBSD 1
36#else
37# define SANITIZER_NETBSD 0
38#endif
39
40#if defined(__OpenBSD__)
41# define SANITIZER_OPENBSD 1
42#else
43# define SANITIZER_OPENBSD 0
44#endif
45
46#if defined(__sun__) && defined(__svr4__)
47# define SANITIZER_SOLARIS 1
48#else
49# define SANITIZER_SOLARIS 0
50#endif
51
52#if defined(__APPLE__)
53# define SANITIZER_MAC 1
54# include <TargetConditionals.h>
55# if TARGET_OS_IPHONE
56# define SANITIZER_IOS 1
57# else
58# define SANITIZER_IOS 0
59# endif
60# if TARGET_OS_SIMULATOR
61# define SANITIZER_IOSSIM 1
62# else
63# define SANITIZER_IOSSIM 0
64# endif
65#else
66# define SANITIZER_MAC 0
67# define SANITIZER_IOS 0
68# define SANITIZER_IOSSIM 0
69#endif
70
71#if defined(__APPLE__) && TARGET_OS_IPHONE && TARGET_OS_WATCH
72# define SANITIZER_WATCHOS 1
73#else
74# define SANITIZER_WATCHOS 0
75#endif
76
77#if defined(__APPLE__) && TARGET_OS_IPHONE && TARGET_OS_TV
78# define SANITIZER_TVOS 1
79#else
80# define SANITIZER_TVOS 0
81#endif
82
83#if defined(_WIN32)
84# define SANITIZER_WINDOWS 1
85#else
86# define SANITIZER_WINDOWS 0
87#endif
88
89#if defined(_WIN64)
90# define SANITIZER_WINDOWS64 1
91#else
92# define SANITIZER_WINDOWS64 0
93#endif
94
95#if defined(__ANDROID__)
96# define SANITIZER_ANDROID 1
97#else
98# define SANITIZER_ANDROID 0
99#endif
100
101#if defined(__Fuchsia__)
102# define SANITIZER_FUCHSIA 1
103#else
104# define SANITIZER_FUCHSIA 0
105#endif
106
107#if defined(__rtems__)
108# define SANITIZER_RTEMS 1
109#else
110# define SANITIZER_RTEMS 0
111#endif
112
113#define SANITIZER_POSIX \
114 (SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_MAC || \
115 SANITIZER_NETBSD || SANITIZER_OPENBSD || SANITIZER_SOLARIS)
116
117#if __LP64__ || defined(_WIN64)
118# define SANITIZER_WORDSIZE 64
119#else
120# define SANITIZER_WORDSIZE 32
121#endif
122
123#if SANITIZER_WORDSIZE == 64
124# define FIRST_32_SECOND_64(a, b) (b)
125#else
126# define FIRST_32_SECOND_64(a, b) (a)
127#endif
128
129#if defined(__x86_64__) && !defined(_LP64)
130# define SANITIZER_X32 1
131#else
132# define SANITIZER_X32 0
133#endif
134
135#if defined(__i386__) || defined(_M_IX86)
136# define SANITIZER_I386 1
137#else
138# define SANITIZER_I386 0
139#endif
140
141#if defined(__mips__)
142# define SANITIZER_MIPS 1
143# if defined(__mips64)
144# define SANITIZER_MIPS32 0
145# define SANITIZER_MIPS64 1
146# else
147# define SANITIZER_MIPS32 1
148# define SANITIZER_MIPS64 0
149# endif
150#else
151# define SANITIZER_MIPS 0
152# define SANITIZER_MIPS32 0
153# define SANITIZER_MIPS64 0
154#endif
155
156#if defined(__s390__)
157# define SANITIZER_S390 1
158# if defined(__s390x__)
159# define SANITIZER_S390_31 0
160# define SANITIZER_S390_64 1
161# else
162# define SANITIZER_S390_31 1
163# define SANITIZER_S390_64 0
164# endif
165#else
166# define SANITIZER_S390 0
167# define SANITIZER_S390_31 0
168# define SANITIZER_S390_64 0
169#endif
170
171#if defined(__powerpc__)
172# define SANITIZER_PPC 1
173# if defined(__powerpc64__)
174# define SANITIZER_PPC32 0
175# define SANITIZER_PPC64 1
176// 64-bit PPC has two ABIs (v1 and v2). The old powerpc64 target is
177// big-endian, and uses v1 ABI (known for its function descriptors),
178// while the new powerpc64le target is little-endian and uses v2.
179// In theory, you could convince gcc to compile for their evil twins
180// (eg. big-endian v2), but you won't find such combinations in the wild
181// (it'd require bootstrapping a whole system, which would be quite painful
182// - there's no target triple for that). LLVM doesn't support them either.
183# if _CALL_ELF == 2
184# define SANITIZER_PPC64V1 0
185# define SANITIZER_PPC64V2 1
186# else
187# define SANITIZER_PPC64V1 1
188# define SANITIZER_PPC64V2 0
189# endif
190# else
191# define SANITIZER_PPC32 1
192# define SANITIZER_PPC64 0
193# define SANITIZER_PPC64V1 0
194# define SANITIZER_PPC64V2 0
195# endif
196#else
197# define SANITIZER_PPC 0
198# define SANITIZER_PPC32 0
199# define SANITIZER_PPC64 0
200# define SANITIZER_PPC64V1 0
201# define SANITIZER_PPC64V2 0
202#endif
203
204#if defined(__arm__)
205# define SANITIZER_ARM 1
206#else
207# define SANITIZER_ARM 0
208#endif
209
210#if SANITIZER_SOLARIS && SANITIZER_WORDSIZE == 32
211# define SANITIZER_SOLARIS32 1
212#else
213# define SANITIZER_SOLARIS32 0
214#endif
215
216#if defined(__myriad2__)
217# define SANITIZER_MYRIAD2 1
218#else
219# define SANITIZER_MYRIAD2 0
220#endif
221
222// By default we allow to use SizeClassAllocator64 on 64-bit platform.
223// But in some cases (e.g. AArch64's 39-bit address space) SizeClassAllocator64
224// does not work well and we need to fallback to SizeClassAllocator32.
225// For such platforms build this code with -DSANITIZER_CAN_USE_ALLOCATOR64=0 or
226// change the definition of SANITIZER_CAN_USE_ALLOCATOR64 here.
227#ifndef SANITIZER_CAN_USE_ALLOCATOR64
228# if (SANITIZER_ANDROID && defined(__aarch64__)) || SANITIZER_FUCHSIA
229# define SANITIZER_CAN_USE_ALLOCATOR64 1
230# elif defined(__mips64) || defined(__aarch64__)
231# define SANITIZER_CAN_USE_ALLOCATOR64 0
232# else
233# define SANITIZER_CAN_USE_ALLOCATOR64 (SANITIZER_WORDSIZE == 64)
234# endif
235#endif
236
237// The range of addresses which can be returned my mmap.
238// FIXME: this value should be different on different platforms. Larger values
239// will still work but will consume more memory for TwoLevelByteMap.
240#if defined(__mips__)
241# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 40)
242#elif defined(__aarch64__)
243# if SANITIZER_MAC
244// Darwin iOS/ARM64 has a 36-bit VMA, 64GiB VM
245# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 36)
246# else
247# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 48)
248# endif
249#elif defined(__sparc__)
250#define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 52)
251#else
252# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 47)
253#endif
254
255// Whether the addresses are sign-extended from the VMA range to the word.
256// The SPARC64 Linux port implements this to split the VMA space into two
257// non-contiguous halves with a huge hole in the middle.
258#if defined(__sparc__) && SANITIZER_WORDSIZE == 64
259#define SANITIZER_SIGN_EXTENDED_ADDRESSES 1
260#else
261#define SANITIZER_SIGN_EXTENDED_ADDRESSES 0
262#endif
263
264// The AArch64 and RISC-V linux ports use the canonical syscall set as
265// mandated by the upstream linux community for all new ports. Other ports
266// may still use legacy syscalls.
267#ifndef SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
268# if (defined(__aarch64__) || defined(__riscv)) && SANITIZER_LINUX
269# define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 1
270# else
271# define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 0
272# endif
273#endif
274
275// udi16 syscalls can only be used when the following conditions are
276// met:
277// * target is one of arm32, x86-32, sparc32, sh or m68k
278// * libc version is libc5, glibc-2.0, glibc-2.1 or glibc-2.2 to 2.15
279// built against > linux-2.2 kernel headers
280// Since we don't want to include libc headers here, we check the
281// target only.
282#if defined(__arm__) || SANITIZER_X32 || defined(__sparc__)
283#define SANITIZER_USES_UID16_SYSCALLS 1
284#else
285#define SANITIZER_USES_UID16_SYSCALLS 0
286#endif
287
288#if defined(__mips__)
289# define SANITIZER_POINTER_FORMAT_LENGTH FIRST_32_SECOND_64(8, 10)
290#else
291# define SANITIZER_POINTER_FORMAT_LENGTH FIRST_32_SECOND_64(8, 12)
292#endif
293
294/// \macro MSC_PREREQ
295/// \brief Is the compiler MSVC of at least the specified version?
296/// The common \param version values to check for are:
297/// * 1800: Microsoft Visual Studio 2013 / 12.0
298/// * 1900: Microsoft Visual Studio 2015 / 14.0
299#ifdef _MSC_VER
300# define MSC_PREREQ(version) (_MSC_VER >= (version))
301#else
302# define MSC_PREREQ(version) 0
303#endif
304
305#if SANITIZER_MAC && !(defined(__arm64__) && SANITIZER_IOS)
306# define SANITIZER_NON_UNIQUE_TYPEINFO 0
307#else
308# define SANITIZER_NON_UNIQUE_TYPEINFO 1
309#endif
310
311// On linux, some architectures had an ABI transition from 64-bit long double
312// (ie. same as double) to 128-bit long double. On those, glibc symbols
313// involving long doubles come in two versions, and we need to pass the
314// correct one to dlvsym when intercepting them.
315#if SANITIZER_LINUX && (SANITIZER_S390 || SANITIZER_PPC32 || SANITIZER_PPC64V1)
316#define SANITIZER_NLDBL_VERSION "GLIBC_2.4"
317#endif
318
319#if SANITIZER_GO == 0
320# define SANITIZER_GO 0
321#endif
322
323// On PowerPC and ARM Thumb, calling pthread_exit() causes LSan to detect leaks.
324// pthread_exit() performs unwinding that leads to dlopen'ing libgcc_s.so.
325// dlopen mallocs "libgcc_s.so" string which confuses LSan, it fails to realize
326// that this allocation happens in dynamic linker and should be ignored.
327#if SANITIZER_PPC || defined(__thumb__)
328# define SANITIZER_SUPPRESS_LEAK_ON_PTHREAD_EXIT 1
329#else
330# define SANITIZER_SUPPRESS_LEAK_ON_PTHREAD_EXIT 0
331#endif
332
333#if SANITIZER_FREEBSD || SANITIZER_MAC || SANITIZER_NETBSD || \
334 SANITIZER_OPENBSD || SANITIZER_SOLARIS
335# define SANITIZER_MADVISE_DONTNEED MADV_FREE
336#else
337# define SANITIZER_MADVISE_DONTNEED MADV_DONTNEED
338#endif
339
340// Older gcc have issues aligning to a constexpr, and require an integer.
341// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56859 among others.
342#if defined(__powerpc__) || defined(__powerpc64__)
343# define SANITIZER_CACHE_LINE_SIZE 128
344#else
345# define SANITIZER_CACHE_LINE_SIZE 64
346#endif
347
348// Enable offline markup symbolizer for Fuchsia and RTEMS.
349#if SANITIZER_FUCHSIA || SANITIZER_RTEMS
350#define SANITIZER_SYMBOLIZER_MARKUP 1
351#else
352#define SANITIZER_SYMBOLIZER_MARKUP 0
353#endif
354
355// Enable ability to support sanitizer initialization that is
356// compatible with the sanitizer library being loaded via
357// `dlopen()`.
358#if SANITIZER_MAC
359#define SANITIZER_SUPPORTS_INIT_FOR_DLOPEN 1
360#else
361#define SANITIZER_SUPPORTS_INIT_FOR_DLOPEN 0
362#endif
363
364#endif // SANITIZER_PLATFORM_H
lib/tsan/sanitizer_common/sanitizer_platform_interceptors.h created+609
...@@ -0,0 +1,609 @@
1//===-- sanitizer_platform_interceptors.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 defines macro telling whether sanitizer tools can/should intercept
10// given library functions on a given platform.
11//
12//===----------------------------------------------------------------------===//
13#ifndef SANITIZER_PLATFORM_INTERCEPTORS_H
14#define SANITIZER_PLATFORM_INTERCEPTORS_H
15
16#include "sanitizer_glibc_version.h"
17#include "sanitizer_internal_defs.h"
18
19#if SANITIZER_POSIX
20# define SI_POSIX 1
21#else
22# define SI_POSIX 0
23#endif
24
25#if !SANITIZER_WINDOWS
26# define SI_WINDOWS 0
27#else
28# define SI_WINDOWS 1
29#endif
30
31#if SI_WINDOWS && SI_POSIX
32# error "Windows is not POSIX!"
33#endif
34
35#if SI_POSIX
36# include "sanitizer_platform_limits_freebsd.h"
37# include "sanitizer_platform_limits_netbsd.h"
38# include "sanitizer_platform_limits_openbsd.h"
39# include "sanitizer_platform_limits_posix.h"
40# include "sanitizer_platform_limits_solaris.h"
41#endif
42
43#if SANITIZER_LINUX && !SANITIZER_ANDROID
44# define SI_LINUX_NOT_ANDROID 1
45#else
46# define SI_LINUX_NOT_ANDROID 0
47#endif
48
49#if SANITIZER_ANDROID
50# define SI_ANDROID 1
51#else
52# define SI_ANDROID 0
53#endif
54
55#if SANITIZER_FREEBSD
56# define SI_FREEBSD 1
57#else
58# define SI_FREEBSD 0
59#endif
60
61#if SANITIZER_NETBSD
62# define SI_NETBSD 1
63#else
64# define SI_NETBSD 0
65#endif
66
67#if SANITIZER_OPENBSD
68#define SI_OPENBSD 1
69#else
70#define SI_OPENBSD 0
71#endif
72
73#if SANITIZER_LINUX
74# define SI_LINUX 1
75#else
76# define SI_LINUX 0
77#endif
78
79#if SANITIZER_MAC
80# define SI_MAC 1
81# define SI_NOT_MAC 0
82#else
83# define SI_MAC 0
84# define SI_NOT_MAC 1
85#endif
86
87#if SANITIZER_IOS
88# define SI_IOS 1
89#else
90# define SI_IOS 0
91#endif
92
93#if SANITIZER_IOSSIM
94# define SI_IOSSIM 1
95#else
96# define SI_IOSSIM 0
97#endif
98
99#if SANITIZER_WATCHOS
100# define SI_WATCHOS 1
101#else
102# define SI_WATCHOS 0
103#endif
104
105#if SANITIZER_TVOS
106# define SI_TVOS 1
107#else
108# define SI_TVOS 0
109#endif
110
111#if SANITIZER_FUCHSIA
112# define SI_NOT_FUCHSIA 0
113#else
114# define SI_NOT_FUCHSIA 1
115#endif
116
117#if SANITIZER_RTEMS
118# define SI_NOT_RTEMS 0
119#else
120# define SI_NOT_RTEMS 1
121#endif
122
123#if SANITIZER_SOLARIS
124# define SI_SOLARIS 1
125#else
126# define SI_SOLARIS 0
127#endif
128
129#if SANITIZER_SOLARIS32
130# define SI_SOLARIS32 1
131#else
132# define SI_SOLARIS32 0
133#endif
134
135#if SANITIZER_POSIX && !SANITIZER_MAC
136# define SI_POSIX_NOT_MAC 1
137#else
138# define SI_POSIX_NOT_MAC 0
139#endif
140
141#if SANITIZER_LINUX && !SANITIZER_FREEBSD
142# define SI_LINUX_NOT_FREEBSD 1
143# else
144# define SI_LINUX_NOT_FREEBSD 0
145#endif
146
147#define SANITIZER_INTERCEPT_STRLEN SI_NOT_FUCHSIA
148#define SANITIZER_INTERCEPT_STRNLEN (SI_NOT_MAC && SI_NOT_FUCHSIA)
149#define SANITIZER_INTERCEPT_STRCMP SI_NOT_FUCHSIA
150#define SANITIZER_INTERCEPT_STRSTR SI_NOT_FUCHSIA
151#define SANITIZER_INTERCEPT_STRCASESTR SI_POSIX
152#define SANITIZER_INTERCEPT_STRTOK SI_NOT_FUCHSIA
153#define SANITIZER_INTERCEPT_STRCHR SI_NOT_FUCHSIA
154#define SANITIZER_INTERCEPT_STRCHRNUL SI_POSIX_NOT_MAC
155#define SANITIZER_INTERCEPT_STRRCHR SI_NOT_FUCHSIA
156#define SANITIZER_INTERCEPT_STRSPN SI_NOT_FUCHSIA
157#define SANITIZER_INTERCEPT_STRPBRK SI_NOT_FUCHSIA
158#define SANITIZER_INTERCEPT_TEXTDOMAIN SI_LINUX_NOT_ANDROID || SI_SOLARIS
159#define SANITIZER_INTERCEPT_STRCASECMP SI_POSIX
160#define SANITIZER_INTERCEPT_MEMSET 1
161#define SANITIZER_INTERCEPT_MEMMOVE 1
162#define SANITIZER_INTERCEPT_MEMCPY 1
163#define SANITIZER_INTERCEPT_MEMCMP SI_NOT_FUCHSIA
164#define SANITIZER_INTERCEPT_BCMP \
165 SANITIZER_INTERCEPT_MEMCMP && \
166 ((SI_POSIX && _GNU_SOURCE) || SI_NETBSD || SI_OPENBSD || SI_FREEBSD)
167#define SANITIZER_INTERCEPT_STRNDUP SI_POSIX
168#define SANITIZER_INTERCEPT___STRNDUP SI_LINUX_NOT_FREEBSD
169#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \
170 __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070
171# define SI_MAC_DEPLOYMENT_BELOW_10_7 1
172#else
173# define SI_MAC_DEPLOYMENT_BELOW_10_7 0
174#endif
175// memmem on Darwin doesn't exist on 10.6
176// FIXME: enable memmem on Windows.
177#define SANITIZER_INTERCEPT_MEMMEM (SI_POSIX && !SI_MAC_DEPLOYMENT_BELOW_10_7)
178#define SANITIZER_INTERCEPT_MEMCHR SI_NOT_FUCHSIA
179#define SANITIZER_INTERCEPT_MEMRCHR \
180 (SI_FREEBSD || SI_LINUX || SI_NETBSD || SI_OPENBSD)
181
182#define SANITIZER_INTERCEPT_READ SI_POSIX
183#define SANITIZER_INTERCEPT_PREAD SI_POSIX
184#define SANITIZER_INTERCEPT_WRITE SI_POSIX
185#define SANITIZER_INTERCEPT_PWRITE SI_POSIX
186
187#define SANITIZER_INTERCEPT_FREAD SI_POSIX
188#define SANITIZER_INTERCEPT_FWRITE SI_POSIX
189#define SANITIZER_INTERCEPT_FGETS SI_POSIX
190#define SANITIZER_INTERCEPT_FPUTS SI_POSIX
191#define SANITIZER_INTERCEPT_PUTS SI_POSIX
192
193#define SANITIZER_INTERCEPT_PREAD64 SI_LINUX_NOT_ANDROID || SI_SOLARIS32
194#define SANITIZER_INTERCEPT_PWRITE64 SI_LINUX_NOT_ANDROID || SI_SOLARIS32
195
196#define SANITIZER_INTERCEPT_READV SI_POSIX
197#define SANITIZER_INTERCEPT_WRITEV SI_POSIX
198
199#define SANITIZER_INTERCEPT_PREADV \
200 (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_LINUX_NOT_ANDROID)
201#define SANITIZER_INTERCEPT_PWRITEV SI_LINUX_NOT_ANDROID
202#define SANITIZER_INTERCEPT_PREADV64 SI_LINUX_NOT_ANDROID
203#define SANITIZER_INTERCEPT_PWRITEV64 SI_LINUX_NOT_ANDROID
204
205#define SANITIZER_INTERCEPT_PRCTL SI_LINUX
206
207#define SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS SI_POSIX
208#define SANITIZER_INTERCEPT_STRPTIME SI_POSIX
209
210#define SANITIZER_INTERCEPT_SCANF SI_POSIX
211#define SANITIZER_INTERCEPT_ISOC99_SCANF SI_LINUX_NOT_ANDROID
212
213#ifndef SANITIZER_INTERCEPT_PRINTF
214# define SANITIZER_INTERCEPT_PRINTF SI_POSIX
215# define SANITIZER_INTERCEPT_PRINTF_L (SI_FREEBSD || SI_NETBSD)
216# define SANITIZER_INTERCEPT_ISOC99_PRINTF SI_LINUX_NOT_ANDROID
217#endif
218
219#define SANITIZER_INTERCEPT___PRINTF_CHK \
220 (SANITIZER_INTERCEPT_PRINTF && SI_LINUX_NOT_ANDROID)
221
222#define SANITIZER_INTERCEPT_FREXP SI_NOT_FUCHSIA
223#define SANITIZER_INTERCEPT_FREXPF_FREXPL SI_POSIX
224
225#define SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS SI_POSIX
226#define SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS \
227 (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_MAC || SI_LINUX_NOT_ANDROID || \
228 SI_SOLARIS)
229#define SANITIZER_INTERCEPT_GETPWENT \
230 (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_MAC || SI_LINUX_NOT_ANDROID || \
231 SI_SOLARIS)
232#define SANITIZER_INTERCEPT_FGETGRENT_R \
233 (SI_FREEBSD || SI_OPENBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
234#define SANITIZER_INTERCEPT_FGETPWENT SI_LINUX_NOT_ANDROID || SI_SOLARIS
235#define SANITIZER_INTERCEPT_GETPWENT_R \
236 (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
237#define SANITIZER_INTERCEPT_FGETPWENT_R \
238 (SI_FREEBSD || SI_OPENBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
239#define SANITIZER_INTERCEPT_SETPWENT \
240 (SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
241#define SANITIZER_INTERCEPT_CLOCK_GETTIME \
242 (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_LINUX || SI_SOLARIS)
243#define SANITIZER_INTERCEPT_CLOCK_GETCPUCLOCKID SI_LINUX
244#define SANITIZER_INTERCEPT_GETITIMER SI_POSIX
245#define SANITIZER_INTERCEPT_TIME SI_POSIX
246#define SANITIZER_INTERCEPT_GLOB SI_LINUX_NOT_ANDROID || SI_SOLARIS
247#define SANITIZER_INTERCEPT_GLOB64 SI_LINUX_NOT_ANDROID
248#define SANITIZER_INTERCEPT_WAIT SI_POSIX
249#define SANITIZER_INTERCEPT_INET SI_POSIX
250#define SANITIZER_INTERCEPT_PTHREAD_GETSCHEDPARAM (SI_POSIX && !SI_OPENBSD)
251#define SANITIZER_INTERCEPT_GETADDRINFO SI_POSIX
252#define SANITIZER_INTERCEPT_GETNAMEINFO SI_POSIX
253#define SANITIZER_INTERCEPT_GETSOCKNAME SI_POSIX
254#define SANITIZER_INTERCEPT_GETHOSTBYNAME SI_POSIX
255#define SANITIZER_INTERCEPT_GETHOSTBYNAME2 SI_POSIX && !SI_SOLARIS
256#define SANITIZER_INTERCEPT_GETHOSTBYNAME_R \
257 (SI_FREEBSD || SI_LINUX || SI_SOLARIS)
258#define SANITIZER_INTERCEPT_GETHOSTBYNAME2_R \
259 (SI_FREEBSD || SI_LINUX_NOT_ANDROID)
260#define SANITIZER_INTERCEPT_GETHOSTBYADDR_R \
261 (SI_FREEBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
262#define SANITIZER_INTERCEPT_GETHOSTENT_R \
263 (SI_FREEBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
264#define SANITIZER_INTERCEPT_GETSOCKOPT SI_POSIX
265#define SANITIZER_INTERCEPT_ACCEPT SI_POSIX
266#define SANITIZER_INTERCEPT_ACCEPT4 \
267 (SI_LINUX_NOT_ANDROID || SI_NETBSD || SI_OPENBSD)
268#define SANITIZER_INTERCEPT_PACCEPT SI_NETBSD
269#define SANITIZER_INTERCEPT_MODF SI_POSIX
270#define SANITIZER_INTERCEPT_RECVMSG SI_POSIX
271#define SANITIZER_INTERCEPT_SENDMSG SI_POSIX
272#define SANITIZER_INTERCEPT_RECVMMSG SI_LINUX
273#define SANITIZER_INTERCEPT_SENDMMSG SI_LINUX
274#define SANITIZER_INTERCEPT_SYSMSG SI_LINUX_NOT_ANDROID
275#define SANITIZER_INTERCEPT_GETPEERNAME SI_POSIX
276#define SANITIZER_INTERCEPT_IOCTL SI_POSIX
277#define SANITIZER_INTERCEPT_INET_ATON SI_POSIX
278#define SANITIZER_INTERCEPT_SYSINFO SI_LINUX
279#define SANITIZER_INTERCEPT_READDIR SI_POSIX
280#define SANITIZER_INTERCEPT_READDIR64 SI_LINUX_NOT_ANDROID || SI_SOLARIS32
281#if SI_LINUX_NOT_ANDROID && \
282 (defined(__i386) || defined(__x86_64) || defined(__mips64) || \
283 defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \
284 defined(__s390__))
285#define SANITIZER_INTERCEPT_PTRACE 1
286#else
287#define SANITIZER_INTERCEPT_PTRACE 0
288#endif
289#define SANITIZER_INTERCEPT_SETLOCALE SI_POSIX
290#define SANITIZER_INTERCEPT_GETCWD SI_POSIX
291#define SANITIZER_INTERCEPT_GET_CURRENT_DIR_NAME SI_LINUX_NOT_ANDROID
292#define SANITIZER_INTERCEPT_STRTOIMAX SI_POSIX
293#define SANITIZER_INTERCEPT_MBSTOWCS SI_POSIX
294#define SANITIZER_INTERCEPT_MBSNRTOWCS \
295 (SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
296#define SANITIZER_INTERCEPT_WCSTOMBS SI_POSIX
297#define SANITIZER_INTERCEPT_STRXFRM SI_POSIX
298#define SANITIZER_INTERCEPT___STRXFRM_L SI_LINUX
299#define SANITIZER_INTERCEPT_WCSXFRM SI_POSIX
300#define SANITIZER_INTERCEPT___WCSXFRM_L SI_LINUX
301#define SANITIZER_INTERCEPT_WCSNRTOMBS \
302 (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_MAC || SI_LINUX_NOT_ANDROID || \
303 SI_SOLARIS)
304#define SANITIZER_INTERCEPT_WCRTOMB \
305 (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_MAC || SI_LINUX_NOT_ANDROID || \
306 SI_SOLARIS)
307#define SANITIZER_INTERCEPT_WCTOMB \
308 (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_MAC || SI_LINUX_NOT_ANDROID || \
309 SI_SOLARIS)
310#define SANITIZER_INTERCEPT_TCGETATTR SI_LINUX_NOT_ANDROID || SI_SOLARIS
311#define SANITIZER_INTERCEPT_REALPATH SI_POSIX
312#define SANITIZER_INTERCEPT_CANONICALIZE_FILE_NAME \
313 (SI_LINUX_NOT_ANDROID || SI_SOLARIS)
314#define SANITIZER_INTERCEPT_CONFSTR \
315 (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_MAC || SI_LINUX_NOT_ANDROID || \
316 SI_SOLARIS)
317#define SANITIZER_INTERCEPT_SCHED_GETAFFINITY SI_LINUX_NOT_ANDROID
318#define SANITIZER_INTERCEPT_SCHED_GETPARAM SI_LINUX_NOT_ANDROID || SI_SOLARIS
319#define SANITIZER_INTERCEPT_STRERROR SI_POSIX
320#define SANITIZER_INTERCEPT_STRERROR_R SI_POSIX
321#define SANITIZER_INTERCEPT_XPG_STRERROR_R SI_LINUX_NOT_ANDROID
322#define SANITIZER_INTERCEPT_SCANDIR \
323 (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
324#define SANITIZER_INTERCEPT_SCANDIR64 SI_LINUX_NOT_ANDROID || SI_SOLARIS32
325#define SANITIZER_INTERCEPT_GETGROUPS SI_POSIX
326#define SANITIZER_INTERCEPT_POLL SI_POSIX
327#define SANITIZER_INTERCEPT_PPOLL SI_LINUX_NOT_ANDROID || SI_SOLARIS
328#define SANITIZER_INTERCEPT_WORDEXP \
329 (SI_FREEBSD || SI_NETBSD || (SI_MAC && !SI_IOS) || SI_LINUX_NOT_ANDROID || \
330 SI_SOLARIS)
331#define SANITIZER_INTERCEPT_SIGWAIT SI_POSIX
332#define SANITIZER_INTERCEPT_SIGWAITINFO SI_LINUX_NOT_ANDROID || SI_SOLARIS
333#define SANITIZER_INTERCEPT_SIGTIMEDWAIT SI_LINUX_NOT_ANDROID || SI_SOLARIS
334#define SANITIZER_INTERCEPT_SIGSETOPS \
335 (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
336#define SANITIZER_INTERCEPT_SIGPENDING SI_POSIX
337#define SANITIZER_INTERCEPT_SIGPROCMASK SI_POSIX
338#define SANITIZER_INTERCEPT_PTHREAD_SIGMASK SI_POSIX
339#define SANITIZER_INTERCEPT_BACKTRACE \
340 (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
341#define SANITIZER_INTERCEPT_GETMNTENT SI_LINUX
342#define SANITIZER_INTERCEPT_GETMNTENT_R SI_LINUX_NOT_ANDROID
343#define SANITIZER_INTERCEPT_STATFS \
344 (SI_FREEBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
345#define SANITIZER_INTERCEPT_STATFS64 \
346 (((SI_MAC && !TARGET_CPU_ARM64) && !SI_IOS) || SI_LINUX_NOT_ANDROID)
347#define SANITIZER_INTERCEPT_STATVFS \
348 (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_LINUX_NOT_ANDROID)
349#define SANITIZER_INTERCEPT_STATVFS64 SI_LINUX_NOT_ANDROID
350#define SANITIZER_INTERCEPT_INITGROUPS SI_POSIX
351#define SANITIZER_INTERCEPT_ETHER_NTOA_ATON (SI_POSIX && !SI_OPENBSD)
352#define SANITIZER_INTERCEPT_ETHER_HOST \
353 (SI_FREEBSD || SI_MAC || SI_LINUX_NOT_ANDROID)
354#define SANITIZER_INTERCEPT_ETHER_R (SI_FREEBSD || SI_LINUX_NOT_ANDROID)
355#define SANITIZER_INTERCEPT_SHMCTL \
356 (((SI_FREEBSD || SI_LINUX_NOT_ANDROID) && SANITIZER_WORDSIZE == 64) || \
357 SI_NETBSD || SI_OPENBSD || SI_SOLARIS) // NOLINT
358#define SANITIZER_INTERCEPT_RANDOM_R SI_LINUX_NOT_ANDROID
359#define SANITIZER_INTERCEPT_PTHREAD_ATTR_GET SI_POSIX
360#define SANITIZER_INTERCEPT_PTHREAD_ATTR_GETINHERITSCHED \
361 (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
362#define SANITIZER_INTERCEPT_PTHREAD_ATTR_GETAFFINITY_NP SI_LINUX_NOT_ANDROID
363#define SANITIZER_INTERCEPT_PTHREAD_ATTR_GET_SCHED (SI_POSIX && !SI_OPENBSD)
364#define SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPSHARED \
365 (SI_POSIX && !SI_NETBSD && !SI_OPENBSD)
366#define SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETTYPE (SI_POSIX && !SI_OPENBSD)
367#define SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPROTOCOL \
368 (SI_MAC || SI_NETBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
369#define SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPRIOCEILING \
370 (SI_MAC || SI_NETBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
371#define SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETROBUST \
372 (SI_LINUX_NOT_ANDROID || SI_SOLARIS)
373#define SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETROBUST_NP SI_LINUX_NOT_ANDROID
374#define SANITIZER_INTERCEPT_PTHREAD_RWLOCKATTR_GETPSHARED \
375 (SI_POSIX && !SI_NETBSD && !SI_OPENBSD)
376#define SANITIZER_INTERCEPT_PTHREAD_RWLOCKATTR_GETKIND_NP SI_LINUX_NOT_ANDROID
377#define SANITIZER_INTERCEPT_PTHREAD_CONDATTR_GETPSHARED \
378 (SI_POSIX && !SI_NETBSD && !SI_OPENBSD)
379#define SANITIZER_INTERCEPT_PTHREAD_CONDATTR_GETCLOCK \
380 (SI_LINUX_NOT_ANDROID || SI_SOLARIS)
381#define SANITIZER_INTERCEPT_PTHREAD_BARRIERATTR_GETPSHARED \
382 (SI_LINUX_NOT_ANDROID && !SI_NETBSD && !SI_OPENBSD)
383#define SANITIZER_INTERCEPT_THR_EXIT SI_FREEBSD
384#define SANITIZER_INTERCEPT_TMPNAM SI_POSIX
385#define SANITIZER_INTERCEPT_TMPNAM_R SI_LINUX_NOT_ANDROID || SI_SOLARIS
386#define SANITIZER_INTERCEPT_TTYNAME SI_POSIX
387#define SANITIZER_INTERCEPT_TTYNAME_R SI_POSIX
388#define SANITIZER_INTERCEPT_TEMPNAM SI_POSIX
389#define SANITIZER_INTERCEPT_SINCOS SI_LINUX || SI_SOLARIS
390#define SANITIZER_INTERCEPT_REMQUO SI_POSIX
391#define SANITIZER_INTERCEPT_REMQUOL (SI_POSIX && !SI_NETBSD)
392#define SANITIZER_INTERCEPT_LGAMMA SI_POSIX
393#define SANITIZER_INTERCEPT_LGAMMAL (SI_POSIX && !SI_NETBSD)
394#define SANITIZER_INTERCEPT_LGAMMA_R (SI_FREEBSD || SI_LINUX || SI_SOLARIS)
395#define SANITIZER_INTERCEPT_LGAMMAL_R SI_LINUX_NOT_ANDROID || SI_SOLARIS
396#define SANITIZER_INTERCEPT_DRAND48_R SI_LINUX_NOT_ANDROID
397#define SANITIZER_INTERCEPT_RAND_R \
398 (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_MAC || SI_LINUX_NOT_ANDROID || \
399 SI_SOLARIS)
400#define SANITIZER_INTERCEPT_ICONV \
401 (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
402#define SANITIZER_INTERCEPT_TIMES SI_POSIX
403
404// FIXME: getline seems to be available on OSX 10.7
405#define SANITIZER_INTERCEPT_GETLINE \
406 (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
407
408#define SANITIZER_INTERCEPT__EXIT \
409 (SI_LINUX || SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_MAC || SI_SOLARIS)
410
411#define SANITIZER_INTERCEPT_PTHREAD_MUTEX SI_POSIX
412#define SANITIZER_INTERCEPT___PTHREAD_MUTEX SI_LINUX_NOT_ANDROID
413#define SANITIZER_INTERCEPT___LIBC_MUTEX SI_NETBSD
414#define SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP \
415 (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
416#define SANITIZER_INTERCEPT_PTHREAD_GETNAME_NP \
417 (SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
418
419#define SANITIZER_INTERCEPT_TLS_GET_ADDR \
420 (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
421
422#define SANITIZER_INTERCEPT_LISTXATTR SI_LINUX
423#define SANITIZER_INTERCEPT_GETXATTR SI_LINUX
424#define SANITIZER_INTERCEPT_GETRESID SI_LINUX
425#define SANITIZER_INTERCEPT_GETIFADDRS \
426 (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_LINUX_NOT_ANDROID || SI_MAC || \
427 SI_SOLARIS)
428#define SANITIZER_INTERCEPT_IF_INDEXTONAME \
429 (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_LINUX_NOT_ANDROID || SI_MAC || \
430 SI_SOLARIS)
431#define SANITIZER_INTERCEPT_CAPGET SI_LINUX_NOT_ANDROID
432#if SI_LINUX && defined(__arm__)
433#define SANITIZER_INTERCEPT_AEABI_MEM 1
434#else
435#define SANITIZER_INTERCEPT_AEABI_MEM 0
436#endif
437#define SANITIZER_INTERCEPT___BZERO SI_MAC || SI_LINUX_NOT_ANDROID
438#define SANITIZER_INTERCEPT_BZERO SI_LINUX_NOT_ANDROID
439#define SANITIZER_INTERCEPT_FTIME \
440 (!SI_FREEBSD && !SI_NETBSD && !SI_OPENBSD && SI_POSIX)
441#define SANITIZER_INTERCEPT_XDR SI_LINUX_NOT_ANDROID || SI_SOLARIS
442#define SANITIZER_INTERCEPT_TSEARCH \
443 (SI_LINUX_NOT_ANDROID || SI_MAC || SI_NETBSD || SI_OPENBSD || SI_SOLARIS)
444#define SANITIZER_INTERCEPT_LIBIO_INTERNALS SI_LINUX_NOT_ANDROID
445#define SANITIZER_INTERCEPT_FOPEN SI_POSIX
446#define SANITIZER_INTERCEPT_FOPEN64 SI_LINUX_NOT_ANDROID || SI_SOLARIS32
447#define SANITIZER_INTERCEPT_OPEN_MEMSTREAM \
448 (SI_LINUX_NOT_ANDROID || SI_NETBSD || SI_OPENBSD || SI_SOLARIS)
449#define SANITIZER_INTERCEPT_OBSTACK SI_LINUX_NOT_ANDROID
450#define SANITIZER_INTERCEPT_FFLUSH SI_POSIX
451#define SANITIZER_INTERCEPT_FCLOSE SI_POSIX
452
453#ifndef SANITIZER_INTERCEPT_DLOPEN_DLCLOSE
454#define SANITIZER_INTERCEPT_DLOPEN_DLCLOSE \
455 (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_LINUX_NOT_ANDROID || SI_MAC || \
456 SI_SOLARIS)
457#endif
458
459#define SANITIZER_INTERCEPT_GETPASS \
460 (SI_LINUX_NOT_ANDROID || SI_MAC || SI_NETBSD || SI_OPENBSD)
461#define SANITIZER_INTERCEPT_TIMERFD SI_LINUX_NOT_ANDROID
462
463#define SANITIZER_INTERCEPT_MLOCKX SI_POSIX
464#define SANITIZER_INTERCEPT_FOPENCOOKIE SI_LINUX_NOT_ANDROID
465#define SANITIZER_INTERCEPT_SEM \
466 (SI_LINUX || SI_FREEBSD || SI_NETBSD || SI_SOLARIS)
467#define SANITIZER_INTERCEPT_PTHREAD_SETCANCEL SI_POSIX
468#define SANITIZER_INTERCEPT_MINCORE \
469 (SI_LINUX || SI_NETBSD || SI_OPENBSD || SI_SOLARIS)
470#define SANITIZER_INTERCEPT_PROCESS_VM_READV SI_LINUX
471#define SANITIZER_INTERCEPT_CTERMID \
472 (SI_LINUX || SI_MAC || SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_SOLARIS)
473#define SANITIZER_INTERCEPT_CTERMID_R (SI_MAC || SI_FREEBSD || SI_SOLARIS)
474
475#define SANITIZER_INTERCEPTOR_HOOKS \
476 (SI_LINUX || SI_MAC || SI_WINDOWS || SI_NETBSD)
477#define SANITIZER_INTERCEPT_RECV_RECVFROM SI_POSIX
478#define SANITIZER_INTERCEPT_SEND_SENDTO SI_POSIX
479#define SANITIZER_INTERCEPT_EVENTFD_READ_WRITE SI_LINUX
480
481#define SANITIZER_INTERCEPT_STAT \
482 (SI_FREEBSD || SI_MAC || SI_ANDROID || SI_NETBSD || SI_OPENBSD || SI_SOLARIS)
483#define SANITIZER_INTERCEPT_LSTAT (SI_NETBSD || SI_FREEBSD)
484#define SANITIZER_INTERCEPT___XSTAT (!SANITIZER_INTERCEPT_STAT && SI_POSIX)
485#define SANITIZER_INTERCEPT___XSTAT64 SI_LINUX_NOT_ANDROID
486#define SANITIZER_INTERCEPT___LXSTAT SANITIZER_INTERCEPT___XSTAT
487#define SANITIZER_INTERCEPT___LXSTAT64 SI_LINUX_NOT_ANDROID
488
489#define SANITIZER_INTERCEPT_UTMP \
490 (SI_POSIX && !SI_MAC && !SI_FREEBSD && !SI_NETBSD)
491#define SANITIZER_INTERCEPT_UTMPX \
492 (SI_LINUX_NOT_ANDROID || SI_MAC || SI_FREEBSD || SI_NETBSD)
493
494#define SANITIZER_INTERCEPT_GETLOADAVG \
495 (SI_LINUX_NOT_ANDROID || SI_MAC || SI_FREEBSD || SI_NETBSD || SI_OPENBSD)
496
497#define SANITIZER_INTERCEPT_MMAP SI_POSIX
498#define SANITIZER_INTERCEPT_MMAP64 SI_LINUX_NOT_ANDROID
499#define SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO \
500 (!SI_FREEBSD && !SI_MAC && !SI_NETBSD && !SI_OPENBSD && SI_NOT_FUCHSIA && \
501 SI_NOT_RTEMS)
502#define SANITIZER_INTERCEPT_MEMALIGN \
503 (!SI_FREEBSD && !SI_MAC && !SI_NETBSD && !SI_OPENBSD && SI_NOT_RTEMS)
504#define SANITIZER_INTERCEPT_PVALLOC \
505 (!SI_FREEBSD && !SI_MAC && !SI_NETBSD && !SI_OPENBSD && SI_NOT_FUCHSIA && \
506 SI_NOT_RTEMS)
507#define SANITIZER_INTERCEPT_CFREE \
508 (!SI_FREEBSD && !SI_MAC && !SI_NETBSD && !SI_OPENBSD && SI_NOT_FUCHSIA && \
509 SI_NOT_RTEMS)
510#define SANITIZER_INTERCEPT_REALLOCARRAY SI_POSIX
511#define SANITIZER_INTERCEPT_ALIGNED_ALLOC (!SI_MAC && SI_NOT_RTEMS)
512#define SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE \
513 (!SI_MAC && !SI_OPENBSD && !SI_NETBSD)
514#define SANITIZER_INTERCEPT_MCHECK_MPROBE SI_LINUX_NOT_ANDROID
515#define SANITIZER_INTERCEPT_WCSCAT SI_POSIX
516#define SANITIZER_INTERCEPT_WCSDUP SI_POSIX
517#define SANITIZER_INTERCEPT_SIGNAL_AND_SIGACTION (!SI_WINDOWS && SI_NOT_FUCHSIA)
518#define SANITIZER_INTERCEPT_BSD_SIGNAL SI_ANDROID
519
520#define SANITIZER_INTERCEPT_ACCT (SI_NETBSD || SI_OPENBSD || SI_FREEBSD)
521#define SANITIZER_INTERCEPT_USER_FROM_UID SI_NETBSD
522#define SANITIZER_INTERCEPT_UID_FROM_USER SI_NETBSD
523#define SANITIZER_INTERCEPT_GROUP_FROM_GID SI_NETBSD
524#define SANITIZER_INTERCEPT_GID_FROM_GROUP SI_NETBSD
525#define SANITIZER_INTERCEPT_ACCESS (SI_NETBSD || SI_OPENBSD || SI_FREEBSD)
526#define SANITIZER_INTERCEPT_FACCESSAT (SI_NETBSD || SI_OPENBSD || SI_FREEBSD)
527#define SANITIZER_INTERCEPT_GETGROUPLIST (SI_NETBSD || SI_OPENBSD)
528#define SANITIZER_INTERCEPT_STRLCPY \
529 (SI_NETBSD || SI_FREEBSD || SI_OPENBSD || SI_MAC || SI_ANDROID)
530
531#define SANITIZER_INTERCEPT_NAME_TO_HANDLE_AT SI_LINUX_NOT_ANDROID
532#define SANITIZER_INTERCEPT_OPEN_BY_HANDLE_AT SI_LINUX_NOT_ANDROID
533
534#define SANITIZER_INTERCEPT_READLINK SI_POSIX
535#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \
536 __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101000
537# define SI_MAC_DEPLOYMENT_BELOW_10_10 1
538#else
539# define SI_MAC_DEPLOYMENT_BELOW_10_10 0
540#endif
541#define SANITIZER_INTERCEPT_READLINKAT \
542 (SI_POSIX && !SI_MAC_DEPLOYMENT_BELOW_10_10)
543
544#define SANITIZER_INTERCEPT_DEVNAME (SI_NETBSD || SI_OPENBSD || SI_FREEBSD)
545#define SANITIZER_INTERCEPT_DEVNAME_R (SI_NETBSD || SI_FREEBSD)
546#define SANITIZER_INTERCEPT_FGETLN (SI_NETBSD || SI_FREEBSD)
547#define SANITIZER_INTERCEPT_STRMODE (SI_NETBSD || SI_FREEBSD)
548#define SANITIZER_INTERCEPT_TTYENT SI_NETBSD
549#define SANITIZER_INTERCEPT_PROTOENT (SI_NETBSD || SI_LINUX)
550#define SANITIZER_INTERCEPT_PROTOENT_R (SI_LINUX_NOT_ANDROID)
551#define SANITIZER_INTERCEPT_NETENT SI_NETBSD
552#define SANITIZER_INTERCEPT_SETVBUF (SI_NETBSD || SI_FREEBSD || \
553 SI_LINUX || SI_MAC)
554#define SANITIZER_INTERCEPT_GETMNTINFO (SI_NETBSD || SI_FREEBSD || SI_MAC)
555#define SANITIZER_INTERCEPT_MI_VECTOR_HASH SI_NETBSD
556#define SANITIZER_INTERCEPT_GETVFSSTAT SI_NETBSD
557#define SANITIZER_INTERCEPT_REGEX (SI_NETBSD || SI_FREEBSD || SI_LINUX)
558#define SANITIZER_INTERCEPT_REGEXSUB SI_NETBSD
559#define SANITIZER_INTERCEPT_FTS (SI_NETBSD || SI_FREEBSD)
560#define SANITIZER_INTERCEPT_SYSCTL (SI_NETBSD || SI_FREEBSD || SI_MAC)
561#define SANITIZER_INTERCEPT_ASYSCTL SI_NETBSD
562#define SANITIZER_INTERCEPT_SYSCTLGETMIBINFO SI_NETBSD
563#define SANITIZER_INTERCEPT_NL_LANGINFO (SI_NETBSD || SI_FREEBSD || SI_MAC)
564#define SANITIZER_INTERCEPT_MODCTL SI_NETBSD
565#define SANITIZER_INTERCEPT_CAPSICUM SI_FREEBSD
566#define SANITIZER_INTERCEPT_STRTONUM (SI_NETBSD || SI_FREEBSD)
567#define SANITIZER_INTERCEPT_FPARSELN SI_NETBSD
568#define SANITIZER_INTERCEPT_STATVFS1 SI_NETBSD
569#define SANITIZER_INTERCEPT_STRTOI SI_NETBSD
570#define SANITIZER_INTERCEPT_CAPSICUM SI_FREEBSD
571#define SANITIZER_INTERCEPT_SHA1 SI_NETBSD
572#define SANITIZER_INTERCEPT_MD4 SI_NETBSD
573#define SANITIZER_INTERCEPT_RMD160 SI_NETBSD
574#define SANITIZER_INTERCEPT_MD5 SI_NETBSD
575#define SANITIZER_INTERCEPT_FSEEK (SI_NETBSD || SI_FREEBSD)
576#define SANITIZER_INTERCEPT_MD2 SI_NETBSD
577#define SANITIZER_INTERCEPT_SHA2 SI_NETBSD
578#define SANITIZER_INTERCEPT_CDB SI_NETBSD
579#define SANITIZER_INTERCEPT_VIS (SI_NETBSD || SI_FREEBSD)
580#define SANITIZER_INTERCEPT_POPEN SI_POSIX
581#define SANITIZER_INTERCEPT_POPENVE SI_NETBSD
582#define SANITIZER_INTERCEPT_PCLOSE SI_POSIX
583#define SANITIZER_INTERCEPT_FUNOPEN (SI_NETBSD || SI_FREEBSD)
584#define SANITIZER_INTERCEPT_FUNOPEN2 SI_NETBSD
585#define SANITIZER_INTERCEPT_GETFSENT (SI_FREEBSD || SI_NETBSD || SI_MAC)
586#define SANITIZER_INTERCEPT_ARC4RANDOM (SI_FREEBSD || SI_NETBSD || SI_MAC)
587#define SANITIZER_INTERCEPT_FDEVNAME SI_FREEBSD
588#define SANITIZER_INTERCEPT_GETUSERSHELL (SI_POSIX && !SI_ANDROID)
589#define SANITIZER_INTERCEPT_SL_INIT (SI_FREEBSD || SI_NETBSD)
590#define SANITIZER_INTERCEPT_CRYPT (SI_POSIX && !SI_ANDROID)
591#define SANITIZER_INTERCEPT_CRYPT_R (SI_LINUX && !SI_ANDROID)
592
593#define SANITIZER_INTERCEPT_GETRANDOM \
594 ((SI_LINUX && __GLIBC_PREREQ(2, 25)) || SI_FREEBSD)
595#define SANITIZER_INTERCEPT___CXA_ATEXIT SI_NETBSD
596#define SANITIZER_INTERCEPT_ATEXIT SI_NETBSD
597#define SANITIZER_INTERCEPT_PTHREAD_ATFORK SI_NETBSD
598#define SANITIZER_INTERCEPT_GETENTROPY SI_FREEBSD
599#define SANITIZER_INTERCEPT_QSORT \
600 (SI_POSIX && !SI_IOSSIM && !SI_WATCHOS && !SI_TVOS && !SI_ANDROID)
601#define SANITIZER_INTERCEPT_QSORT_R (SI_LINUX && !SI_ANDROID)
602// sigaltstack on i386 macOS cannot be intercepted due to setjmp()
603// calling it and assuming that it does not clobber registers.
604#define SANITIZER_INTERCEPT_SIGALTSTACK \
605 (SI_POSIX && !(SANITIZER_MAC && SANITIZER_I386))
606#define SANITIZER_INTERCEPT_UNAME (SI_POSIX && !SI_FREEBSD)
607#define SANITIZER_INTERCEPT___XUNAME SI_FREEBSD
608
609#endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H
lib/tsan/sanitizer_common/sanitizer_platform_limits_freebsd.cpp created+531
...@@ -0,0 +1,531 @@
1//===-- sanitizer_platform_limits_freebsd.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 Sanitizer common code.
10//
11// Sizes and layouts of platform-specific FreeBSD data structures.
12//===----------------------------------------------------------------------===//
13
14#include "sanitizer_platform.h"
15
16#if SANITIZER_FREEBSD
17
18#include <sys/capsicum.h>
19#include <sys/consio.h>
20#include <sys/filio.h>
21#include <sys/ipc.h>
22#include <sys/kbio.h>
23#include <sys/link_elf.h>
24#include <sys/mman.h>
25#include <sys/mount.h>
26#include <sys/mqueue.h>
27#include <sys/msg.h>
28#include <sys/mtio.h>
29#include <sys/ptrace.h>
30#include <sys/resource.h>
31#include <sys/signal.h>
32#include <sys/socket.h>
33#include <sys/sockio.h>
34#include <sys/soundcard.h>
35#include <sys/stat.h>
36#include <sys/statvfs.h>
37#include <sys/time.h>
38#include <sys/timeb.h>
39#include <sys/times.h>
40#include <sys/timespec.h>
41#include <sys/types.h>
42#include <sys/ucontext.h>
43#include <sys/utsname.h>
44//
45#include <arpa/inet.h>
46#include <net/ethernet.h>
47#include <net/if.h>
48#include <net/ppp_defs.h>
49#include <net/route.h>
50#include <netdb.h>
51#include <netinet/in.h>
52#include <netinet/ip_mroute.h>
53//
54#include <dirent.h>
55#include <dlfcn.h>
56#include <fstab.h>
57#include <fts.h>
58#include <glob.h>
59#include <grp.h>
60#include <ifaddrs.h>
61#include <limits.h>
62#include <poll.h>
63#include <pthread.h>
64#include <pwd.h>
65#include <regex.h>
66#include <semaphore.h>
67#include <signal.h>
68#include <stddef.h>
69#include <stdio.h>
70#include <stringlist.h>
71#include <term.h>
72#include <termios.h>
73#include <time.h>
74#include <utime.h>
75#include <utmpx.h>
76#include <vis.h>
77#include <wchar.h>
78#include <wordexp.h>
79
80#define _KERNEL // to declare 'shminfo' structure
81#include <sys/shm.h>
82#undef _KERNEL
83
84#undef INLINE // to avoid clashes with sanitizers' definitions
85
86#undef IOC_DIRMASK
87
88// Include these after system headers to avoid name clashes and ambiguities.
89#include "sanitizer_internal_defs.h"
90#include "sanitizer_libc.h"
91#include "sanitizer_platform_limits_freebsd.h"
92
93namespace __sanitizer {
94void *__sanitizer_get_link_map_by_dlopen_handle(void *handle) {
95 void *p = nullptr;
96 return internal_dlinfo(handle, RTLD_DI_LINKMAP, &p) == 0 ? p : nullptr;
97}
98
99unsigned struct_cap_rights_sz = sizeof(cap_rights_t);
100unsigned struct_utsname_sz = sizeof(struct utsname);
101unsigned struct_stat_sz = sizeof(struct stat);
102unsigned struct_rusage_sz = sizeof(struct rusage);
103unsigned struct_tm_sz = sizeof(struct tm);
104unsigned struct_passwd_sz = sizeof(struct passwd);
105unsigned struct_group_sz = sizeof(struct group);
106unsigned siginfo_t_sz = sizeof(siginfo_t);
107unsigned struct_sigaction_sz = sizeof(struct sigaction);
108unsigned struct_stack_t_sz = sizeof(stack_t);
109unsigned struct_itimerval_sz = sizeof(struct itimerval);
110unsigned pthread_t_sz = sizeof(pthread_t);
111unsigned pthread_mutex_t_sz = sizeof(pthread_mutex_t);
112unsigned pthread_cond_t_sz = sizeof(pthread_cond_t);
113unsigned pid_t_sz = sizeof(pid_t);
114unsigned timeval_sz = sizeof(timeval);
115unsigned uid_t_sz = sizeof(uid_t);
116unsigned gid_t_sz = sizeof(gid_t);
117unsigned fpos_t_sz = sizeof(fpos_t);
118unsigned mbstate_t_sz = sizeof(mbstate_t);
119unsigned sigset_t_sz = sizeof(sigset_t);
120unsigned struct_timezone_sz = sizeof(struct timezone);
121unsigned struct_tms_sz = sizeof(struct tms);
122unsigned struct_sigevent_sz = sizeof(struct sigevent);
123unsigned struct_sched_param_sz = sizeof(struct sched_param);
124unsigned struct_statfs_sz = sizeof(struct statfs);
125unsigned struct_sockaddr_sz = sizeof(struct sockaddr);
126unsigned ucontext_t_sz = sizeof(ucontext_t);
127unsigned struct_rlimit_sz = sizeof(struct rlimit);
128unsigned struct_timespec_sz = sizeof(struct timespec);
129unsigned struct_utimbuf_sz = sizeof(struct utimbuf);
130unsigned struct_itimerspec_sz = sizeof(struct itimerspec);
131unsigned struct_timeb_sz = sizeof(struct timeb);
132unsigned struct_msqid_ds_sz = sizeof(struct msqid_ds);
133unsigned struct_mq_attr_sz = sizeof(struct mq_attr);
134unsigned struct_statvfs_sz = sizeof(struct statvfs);
135unsigned struct_shminfo_sz = sizeof(struct shminfo);
136unsigned struct_shm_info_sz = sizeof(struct shm_info);
137unsigned struct_regmatch_sz = sizeof(regmatch_t);
138unsigned struct_regex_sz = sizeof(regex_t);
139unsigned struct_fstab_sz = sizeof(struct fstab);
140unsigned struct_FTS_sz = sizeof(FTS);
141unsigned struct_FTSENT_sz = sizeof(FTSENT);
142unsigned struct_StringList_sz = sizeof(StringList);
143
144const uptr sig_ign = (uptr)SIG_IGN;
145const uptr sig_dfl = (uptr)SIG_DFL;
146const uptr sig_err = (uptr)SIG_ERR;
147const uptr sa_siginfo = (uptr)SA_SIGINFO;
148
149int shmctl_ipc_stat = (int)IPC_STAT;
150int shmctl_ipc_info = (int)IPC_INFO;
151int shmctl_shm_info = (int)SHM_INFO;
152int shmctl_shm_stat = (int)SHM_STAT;
153unsigned struct_utmpx_sz = sizeof(struct utmpx);
154
155int map_fixed = MAP_FIXED;
156
157int af_inet = (int)AF_INET;
158int af_inet6 = (int)AF_INET6;
159
160uptr __sanitizer_in_addr_sz(int af) {
161 if (af == AF_INET)
162 return sizeof(struct in_addr);
163 else if (af == AF_INET6)
164 return sizeof(struct in6_addr);
165 else
166 return 0;
167}
168
169unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
170int glob_nomatch = GLOB_NOMATCH;
171int glob_altdirfunc = GLOB_ALTDIRFUNC;
172
173unsigned path_max = PATH_MAX;
174
175// ioctl arguments
176unsigned struct_ifreq_sz = sizeof(struct ifreq);
177unsigned struct_termios_sz = sizeof(struct termios);
178unsigned struct_winsize_sz = sizeof(struct winsize);
179#if SOUND_VERSION >= 0x040000
180unsigned struct_copr_buffer_sz = 0;
181unsigned struct_copr_debug_buf_sz = 0;
182unsigned struct_copr_msg_sz = 0;
183#else
184unsigned struct_copr_buffer_sz = sizeof(struct copr_buffer);
185unsigned struct_copr_debug_buf_sz = sizeof(struct copr_debug_buf);
186unsigned struct_copr_msg_sz = sizeof(struct copr_msg);
187#endif
188unsigned struct_midi_info_sz = sizeof(struct midi_info);
189unsigned struct_mtget_sz = sizeof(struct mtget);
190unsigned struct_mtop_sz = sizeof(struct mtop);
191unsigned struct_sbi_instrument_sz = sizeof(struct sbi_instrument);
192unsigned struct_seq_event_rec_sz = sizeof(struct seq_event_rec);
193unsigned struct_synth_info_sz = sizeof(struct synth_info);
194unsigned struct_audio_buf_info_sz = sizeof(struct audio_buf_info);
195unsigned struct_ppp_stats_sz = sizeof(struct ppp_stats);
196unsigned struct_sioc_sg_req_sz = sizeof(struct sioc_sg_req);
197unsigned struct_sioc_vif_req_sz = sizeof(struct sioc_vif_req);
198const unsigned long __sanitizer_bufsiz = BUFSIZ;
199
200const unsigned IOCTL_NOT_PRESENT = 0;
201
202unsigned IOCTL_FIOASYNC = FIOASYNC;
203unsigned IOCTL_FIOCLEX = FIOCLEX;
204unsigned IOCTL_FIOGETOWN = FIOGETOWN;
205unsigned IOCTL_FIONBIO = FIONBIO;
206unsigned IOCTL_FIONCLEX = FIONCLEX;
207unsigned IOCTL_FIOSETOWN = FIOSETOWN;
208unsigned IOCTL_SIOCADDMULTI = SIOCADDMULTI;
209unsigned IOCTL_SIOCATMARK = SIOCATMARK;
210unsigned IOCTL_SIOCDELMULTI = SIOCDELMULTI;
211unsigned IOCTL_SIOCGIFADDR = SIOCGIFADDR;
212unsigned IOCTL_SIOCGIFBRDADDR = SIOCGIFBRDADDR;
213unsigned IOCTL_SIOCGIFCONF = SIOCGIFCONF;
214unsigned IOCTL_SIOCGIFDSTADDR = SIOCGIFDSTADDR;
215unsigned IOCTL_SIOCGIFFLAGS = SIOCGIFFLAGS;
216unsigned IOCTL_SIOCGIFMETRIC = SIOCGIFMETRIC;
217unsigned IOCTL_SIOCGIFMTU = SIOCGIFMTU;
218unsigned IOCTL_SIOCGIFNETMASK = SIOCGIFNETMASK;
219unsigned IOCTL_SIOCGPGRP = SIOCGPGRP;
220unsigned IOCTL_SIOCSIFADDR = SIOCSIFADDR;
221unsigned IOCTL_SIOCSIFBRDADDR = SIOCSIFBRDADDR;
222unsigned IOCTL_SIOCSIFDSTADDR = SIOCSIFDSTADDR;
223unsigned IOCTL_SIOCSIFFLAGS = SIOCSIFFLAGS;
224unsigned IOCTL_SIOCSIFMETRIC = SIOCSIFMETRIC;
225unsigned IOCTL_SIOCSIFMTU = SIOCSIFMTU;
226unsigned IOCTL_SIOCSIFNETMASK = SIOCSIFNETMASK;
227unsigned IOCTL_SIOCSPGRP = SIOCSPGRP;
228unsigned IOCTL_TIOCCONS = TIOCCONS;
229unsigned IOCTL_TIOCEXCL = TIOCEXCL;
230unsigned IOCTL_TIOCGETD = TIOCGETD;
231unsigned IOCTL_TIOCGPGRP = TIOCGPGRP;
232unsigned IOCTL_TIOCGWINSZ = TIOCGWINSZ;
233unsigned IOCTL_TIOCMBIC = TIOCMBIC;
234unsigned IOCTL_TIOCMBIS = TIOCMBIS;
235unsigned IOCTL_TIOCMGET = TIOCMGET;
236unsigned IOCTL_TIOCMSET = TIOCMSET;
237unsigned IOCTL_TIOCNOTTY = TIOCNOTTY;
238unsigned IOCTL_TIOCNXCL = TIOCNXCL;
239unsigned IOCTL_TIOCOUTQ = TIOCOUTQ;
240unsigned IOCTL_TIOCPKT = TIOCPKT;
241unsigned IOCTL_TIOCSCTTY = TIOCSCTTY;
242unsigned IOCTL_TIOCSETD = TIOCSETD;
243unsigned IOCTL_TIOCSPGRP = TIOCSPGRP;
244unsigned IOCTL_TIOCSTI = TIOCSTI;
245unsigned IOCTL_TIOCSWINSZ = TIOCSWINSZ;
246unsigned IOCTL_SIOCGETSGCNT = SIOCGETSGCNT;
247unsigned IOCTL_SIOCGETVIFCNT = SIOCGETVIFCNT;
248unsigned IOCTL_MTIOCGET = MTIOCGET;
249unsigned IOCTL_MTIOCTOP = MTIOCTOP;
250unsigned IOCTL_SNDCTL_DSP_GETBLKSIZE = SNDCTL_DSP_GETBLKSIZE;
251unsigned IOCTL_SNDCTL_DSP_GETFMTS = SNDCTL_DSP_GETFMTS;
252unsigned IOCTL_SNDCTL_DSP_NONBLOCK = SNDCTL_DSP_NONBLOCK;
253unsigned IOCTL_SNDCTL_DSP_POST = SNDCTL_DSP_POST;
254unsigned IOCTL_SNDCTL_DSP_RESET = SNDCTL_DSP_RESET;
255unsigned IOCTL_SNDCTL_DSP_SETFMT = SNDCTL_DSP_SETFMT;
256unsigned IOCTL_SNDCTL_DSP_SETFRAGMENT = SNDCTL_DSP_SETFRAGMENT;
257unsigned IOCTL_SNDCTL_DSP_SPEED = SNDCTL_DSP_SPEED;
258unsigned IOCTL_SNDCTL_DSP_STEREO = SNDCTL_DSP_STEREO;
259unsigned IOCTL_SNDCTL_DSP_SUBDIVIDE = SNDCTL_DSP_SUBDIVIDE;
260unsigned IOCTL_SNDCTL_DSP_SYNC = SNDCTL_DSP_SYNC;
261unsigned IOCTL_SNDCTL_FM_4OP_ENABLE = SNDCTL_FM_4OP_ENABLE;
262unsigned IOCTL_SNDCTL_FM_LOAD_INSTR = SNDCTL_FM_LOAD_INSTR;
263unsigned IOCTL_SNDCTL_MIDI_INFO = SNDCTL_MIDI_INFO;
264unsigned IOCTL_SNDCTL_MIDI_PRETIME = SNDCTL_MIDI_PRETIME;
265unsigned IOCTL_SNDCTL_SEQ_CTRLRATE = SNDCTL_SEQ_CTRLRATE;
266unsigned IOCTL_SNDCTL_SEQ_GETINCOUNT = SNDCTL_SEQ_GETINCOUNT;
267unsigned IOCTL_SNDCTL_SEQ_GETOUTCOUNT = SNDCTL_SEQ_GETOUTCOUNT;
268unsigned IOCTL_SNDCTL_SEQ_NRMIDIS = SNDCTL_SEQ_NRMIDIS;
269unsigned IOCTL_SNDCTL_SEQ_NRSYNTHS = SNDCTL_SEQ_NRSYNTHS;
270unsigned IOCTL_SNDCTL_SEQ_OUTOFBAND = SNDCTL_SEQ_OUTOFBAND;
271unsigned IOCTL_SNDCTL_SEQ_PANIC = SNDCTL_SEQ_PANIC;
272unsigned IOCTL_SNDCTL_SEQ_PERCMODE = SNDCTL_SEQ_PERCMODE;
273unsigned IOCTL_SNDCTL_SEQ_RESET = SNDCTL_SEQ_RESET;
274unsigned IOCTL_SNDCTL_SEQ_RESETSAMPLES = SNDCTL_SEQ_RESETSAMPLES;
275unsigned IOCTL_SNDCTL_SEQ_SYNC = SNDCTL_SEQ_SYNC;
276unsigned IOCTL_SNDCTL_SEQ_TESTMIDI = SNDCTL_SEQ_TESTMIDI;
277unsigned IOCTL_SNDCTL_SEQ_THRESHOLD = SNDCTL_SEQ_THRESHOLD;
278unsigned IOCTL_SNDCTL_SYNTH_INFO = SNDCTL_SYNTH_INFO;
279unsigned IOCTL_SNDCTL_SYNTH_MEMAVL = SNDCTL_SYNTH_MEMAVL;
280unsigned IOCTL_SNDCTL_TMR_CONTINUE = SNDCTL_TMR_CONTINUE;
281unsigned IOCTL_SNDCTL_TMR_METRONOME = SNDCTL_TMR_METRONOME;
282unsigned IOCTL_SNDCTL_TMR_SELECT = SNDCTL_TMR_SELECT;
283unsigned IOCTL_SNDCTL_TMR_SOURCE = SNDCTL_TMR_SOURCE;
284unsigned IOCTL_SNDCTL_TMR_START = SNDCTL_TMR_START;
285unsigned IOCTL_SNDCTL_TMR_STOP = SNDCTL_TMR_STOP;
286unsigned IOCTL_SNDCTL_TMR_TEMPO = SNDCTL_TMR_TEMPO;
287unsigned IOCTL_SNDCTL_TMR_TIMEBASE = SNDCTL_TMR_TIMEBASE;
288unsigned IOCTL_SOUND_MIXER_READ_ALTPCM = SOUND_MIXER_READ_ALTPCM;
289unsigned IOCTL_SOUND_MIXER_READ_BASS = SOUND_MIXER_READ_BASS;
290unsigned IOCTL_SOUND_MIXER_READ_CAPS = SOUND_MIXER_READ_CAPS;
291unsigned IOCTL_SOUND_MIXER_READ_CD = SOUND_MIXER_READ_CD;
292unsigned IOCTL_SOUND_MIXER_READ_DEVMASK = SOUND_MIXER_READ_DEVMASK;
293unsigned IOCTL_SOUND_MIXER_READ_ENHANCE = SOUND_MIXER_READ_ENHANCE;
294unsigned IOCTL_SOUND_MIXER_READ_IGAIN = SOUND_MIXER_READ_IGAIN;
295unsigned IOCTL_SOUND_MIXER_READ_IMIX = SOUND_MIXER_READ_IMIX;
296unsigned IOCTL_SOUND_MIXER_READ_LINE = SOUND_MIXER_READ_LINE;
297unsigned IOCTL_SOUND_MIXER_READ_LINE1 = SOUND_MIXER_READ_LINE1;
298unsigned IOCTL_SOUND_MIXER_READ_LINE2 = SOUND_MIXER_READ_LINE2;
299unsigned IOCTL_SOUND_MIXER_READ_LINE3 = SOUND_MIXER_READ_LINE3;
300unsigned IOCTL_SOUND_MIXER_READ_LOUD = SOUND_MIXER_READ_LOUD;
301unsigned IOCTL_SOUND_MIXER_READ_MIC = SOUND_MIXER_READ_MIC;
302unsigned IOCTL_SOUND_MIXER_READ_MUTE = SOUND_MIXER_READ_MUTE;
303unsigned IOCTL_SOUND_MIXER_READ_OGAIN = SOUND_MIXER_READ_OGAIN;
304unsigned IOCTL_SOUND_MIXER_READ_PCM = SOUND_MIXER_READ_PCM;
305unsigned IOCTL_SOUND_MIXER_READ_RECLEV = SOUND_MIXER_READ_RECLEV;
306unsigned IOCTL_SOUND_MIXER_READ_RECMASK = SOUND_MIXER_READ_RECMASK;
307unsigned IOCTL_SOUND_MIXER_READ_RECSRC = SOUND_MIXER_READ_RECSRC;
308unsigned IOCTL_SOUND_MIXER_READ_SPEAKER = SOUND_MIXER_READ_SPEAKER;
309unsigned IOCTL_SOUND_MIXER_READ_STEREODEVS = SOUND_MIXER_READ_STEREODEVS;
310unsigned IOCTL_SOUND_MIXER_READ_SYNTH = SOUND_MIXER_READ_SYNTH;
311unsigned IOCTL_SOUND_MIXER_READ_TREBLE = SOUND_MIXER_READ_TREBLE;
312unsigned IOCTL_SOUND_MIXER_READ_VOLUME = SOUND_MIXER_READ_VOLUME;
313unsigned IOCTL_SOUND_MIXER_WRITE_ALTPCM = SOUND_MIXER_WRITE_ALTPCM;
314unsigned IOCTL_SOUND_MIXER_WRITE_BASS = SOUND_MIXER_WRITE_BASS;
315unsigned IOCTL_SOUND_MIXER_WRITE_CD = SOUND_MIXER_WRITE_CD;
316unsigned IOCTL_SOUND_MIXER_WRITE_ENHANCE = SOUND_MIXER_WRITE_ENHANCE;
317unsigned IOCTL_SOUND_MIXER_WRITE_IGAIN = SOUND_MIXER_WRITE_IGAIN;
318unsigned IOCTL_SOUND_MIXER_WRITE_IMIX = SOUND_MIXER_WRITE_IMIX;
319unsigned IOCTL_SOUND_MIXER_WRITE_LINE = SOUND_MIXER_WRITE_LINE;
320unsigned IOCTL_SOUND_MIXER_WRITE_LINE1 = SOUND_MIXER_WRITE_LINE1;
321unsigned IOCTL_SOUND_MIXER_WRITE_LINE2 = SOUND_MIXER_WRITE_LINE2;
322unsigned IOCTL_SOUND_MIXER_WRITE_LINE3 = SOUND_MIXER_WRITE_LINE3;
323unsigned IOCTL_SOUND_MIXER_WRITE_LOUD = SOUND_MIXER_WRITE_LOUD;
324unsigned IOCTL_SOUND_MIXER_WRITE_MIC = SOUND_MIXER_WRITE_MIC;
325unsigned IOCTL_SOUND_MIXER_WRITE_MUTE = SOUND_MIXER_WRITE_MUTE;
326unsigned IOCTL_SOUND_MIXER_WRITE_OGAIN = SOUND_MIXER_WRITE_OGAIN;
327unsigned IOCTL_SOUND_MIXER_WRITE_PCM = SOUND_MIXER_WRITE_PCM;
328unsigned IOCTL_SOUND_MIXER_WRITE_RECLEV = SOUND_MIXER_WRITE_RECLEV;
329unsigned IOCTL_SOUND_MIXER_WRITE_RECSRC = SOUND_MIXER_WRITE_RECSRC;
330unsigned IOCTL_SOUND_MIXER_WRITE_SPEAKER = SOUND_MIXER_WRITE_SPEAKER;
331unsigned IOCTL_SOUND_MIXER_WRITE_SYNTH = SOUND_MIXER_WRITE_SYNTH;
332unsigned IOCTL_SOUND_MIXER_WRITE_TREBLE = SOUND_MIXER_WRITE_TREBLE;
333unsigned IOCTL_SOUND_MIXER_WRITE_VOLUME = SOUND_MIXER_WRITE_VOLUME;
334unsigned IOCTL_VT_ACTIVATE = VT_ACTIVATE;
335unsigned IOCTL_VT_GETMODE = VT_GETMODE;
336unsigned IOCTL_VT_OPENQRY = VT_OPENQRY;
337unsigned IOCTL_VT_RELDISP = VT_RELDISP;
338unsigned IOCTL_VT_SETMODE = VT_SETMODE;
339unsigned IOCTL_VT_WAITACTIVE = VT_WAITACTIVE;
340unsigned IOCTL_GIO_SCRNMAP = GIO_SCRNMAP;
341unsigned IOCTL_KDDISABIO = KDDISABIO;
342unsigned IOCTL_KDENABIO = KDENABIO;
343unsigned IOCTL_KDGETLED = KDGETLED;
344unsigned IOCTL_KDGETMODE = KDGETMODE;
345unsigned IOCTL_KDGKBMODE = KDGKBMODE;
346unsigned IOCTL_KDGKBTYPE = KDGKBTYPE;
347unsigned IOCTL_KDMKTONE = KDMKTONE;
348unsigned IOCTL_KDSETLED = KDSETLED;
349unsigned IOCTL_KDSETMODE = KDSETMODE;
350unsigned IOCTL_KDSKBMODE = KDSKBMODE;
351unsigned IOCTL_KIOCSOUND = KIOCSOUND;
352unsigned IOCTL_PIO_SCRNMAP = PIO_SCRNMAP;
353unsigned IOCTL_SNDCTL_DSP_GETISPACE = SNDCTL_DSP_GETISPACE;
354
355const int si_SEGV_MAPERR = SEGV_MAPERR;
356const int si_SEGV_ACCERR = SEGV_ACCERR;
357const int unvis_valid = UNVIS_VALID;
358const int unvis_validpush = UNVIS_VALIDPUSH;
359} // namespace __sanitizer
360
361using namespace __sanitizer;
362
363COMPILER_CHECK(sizeof(__sanitizer_pthread_attr_t) >= sizeof(pthread_attr_t));
364
365COMPILER_CHECK(sizeof(socklen_t) == sizeof(unsigned));
366CHECK_TYPE_SIZE(pthread_key_t);
367
368// There are more undocumented fields in dl_phdr_info that we are not interested
369// in.
370COMPILER_CHECK(sizeof(__sanitizer_dl_phdr_info) <= sizeof(dl_phdr_info));
371CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_addr);
372CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_name);
373CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_phdr);
374CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_phnum);
375
376CHECK_TYPE_SIZE(glob_t);
377CHECK_SIZE_AND_OFFSET(glob_t, gl_pathc);
378CHECK_SIZE_AND_OFFSET(glob_t, gl_pathv);
379CHECK_SIZE_AND_OFFSET(glob_t, gl_offs);
380CHECK_SIZE_AND_OFFSET(glob_t, gl_flags);
381CHECK_SIZE_AND_OFFSET(glob_t, gl_closedir);
382CHECK_SIZE_AND_OFFSET(glob_t, gl_readdir);
383CHECK_SIZE_AND_OFFSET(glob_t, gl_opendir);
384CHECK_SIZE_AND_OFFSET(glob_t, gl_lstat);
385CHECK_SIZE_AND_OFFSET(glob_t, gl_stat);
386
387CHECK_TYPE_SIZE(addrinfo);
388CHECK_SIZE_AND_OFFSET(addrinfo, ai_flags);
389CHECK_SIZE_AND_OFFSET(addrinfo, ai_family);
390CHECK_SIZE_AND_OFFSET(addrinfo, ai_socktype);
391CHECK_SIZE_AND_OFFSET(addrinfo, ai_protocol);
392CHECK_SIZE_AND_OFFSET(addrinfo, ai_protocol);
393CHECK_SIZE_AND_OFFSET(addrinfo, ai_addrlen);
394CHECK_SIZE_AND_OFFSET(addrinfo, ai_canonname);
395CHECK_SIZE_AND_OFFSET(addrinfo, ai_addr);
396
397CHECK_TYPE_SIZE(hostent);
398CHECK_SIZE_AND_OFFSET(hostent, h_name);
399CHECK_SIZE_AND_OFFSET(hostent, h_aliases);
400CHECK_SIZE_AND_OFFSET(hostent, h_addrtype);
401CHECK_SIZE_AND_OFFSET(hostent, h_length);
402CHECK_SIZE_AND_OFFSET(hostent, h_addr_list);
403
404CHECK_TYPE_SIZE(iovec);
405CHECK_SIZE_AND_OFFSET(iovec, iov_base);
406CHECK_SIZE_AND_OFFSET(iovec, iov_len);
407
408CHECK_TYPE_SIZE(msghdr);
409CHECK_SIZE_AND_OFFSET(msghdr, msg_name);
410CHECK_SIZE_AND_OFFSET(msghdr, msg_namelen);
411CHECK_SIZE_AND_OFFSET(msghdr, msg_iov);
412CHECK_SIZE_AND_OFFSET(msghdr, msg_iovlen);
413CHECK_SIZE_AND_OFFSET(msghdr, msg_control);
414CHECK_SIZE_AND_OFFSET(msghdr, msg_controllen);
415CHECK_SIZE_AND_OFFSET(msghdr, msg_flags);
416
417CHECK_TYPE_SIZE(cmsghdr);
418CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_len);
419CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_level);
420CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_type);
421
422COMPILER_CHECK(sizeof(__sanitizer_dirent) <= sizeof(dirent));
423CHECK_SIZE_AND_OFFSET(dirent, d_ino);
424CHECK_SIZE_AND_OFFSET(dirent, d_reclen);
425
426CHECK_TYPE_SIZE(ifconf);
427CHECK_SIZE_AND_OFFSET(ifconf, ifc_len);
428CHECK_SIZE_AND_OFFSET(ifconf, ifc_ifcu);
429
430CHECK_TYPE_SIZE(pollfd);
431CHECK_SIZE_AND_OFFSET(pollfd, fd);
432CHECK_SIZE_AND_OFFSET(pollfd, events);
433CHECK_SIZE_AND_OFFSET(pollfd, revents);
434
435CHECK_TYPE_SIZE(nfds_t);
436
437CHECK_TYPE_SIZE(sigset_t);
438
439COMPILER_CHECK(sizeof(__sanitizer_sigaction) == sizeof(struct sigaction));
440// Can't write checks for sa_handler and sa_sigaction due to them being
441// preprocessor macros.
442CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_mask);
443
444CHECK_TYPE_SIZE(wordexp_t);
445CHECK_SIZE_AND_OFFSET(wordexp_t, we_wordc);
446CHECK_SIZE_AND_OFFSET(wordexp_t, we_wordv);
447CHECK_SIZE_AND_OFFSET(wordexp_t, we_offs);
448
449CHECK_TYPE_SIZE(tm);
450CHECK_SIZE_AND_OFFSET(tm, tm_sec);
451CHECK_SIZE_AND_OFFSET(tm, tm_min);
452CHECK_SIZE_AND_OFFSET(tm, tm_hour);
453CHECK_SIZE_AND_OFFSET(tm, tm_mday);
454CHECK_SIZE_AND_OFFSET(tm, tm_mon);
455CHECK_SIZE_AND_OFFSET(tm, tm_year);
456CHECK_SIZE_AND_OFFSET(tm, tm_wday);
457CHECK_SIZE_AND_OFFSET(tm, tm_yday);
458CHECK_SIZE_AND_OFFSET(tm, tm_isdst);
459CHECK_SIZE_AND_OFFSET(tm, tm_gmtoff);
460CHECK_SIZE_AND_OFFSET(tm, tm_zone);
461
462CHECK_TYPE_SIZE(ether_addr);
463
464CHECK_TYPE_SIZE(ipc_perm);
465CHECK_SIZE_AND_OFFSET(ipc_perm, key);
466CHECK_SIZE_AND_OFFSET(ipc_perm, seq);
467CHECK_SIZE_AND_OFFSET(ipc_perm, uid);
468CHECK_SIZE_AND_OFFSET(ipc_perm, gid);
469CHECK_SIZE_AND_OFFSET(ipc_perm, cuid);
470CHECK_SIZE_AND_OFFSET(ipc_perm, cgid);
471
472CHECK_TYPE_SIZE(shmid_ds);
473CHECK_SIZE_AND_OFFSET(shmid_ds, shm_perm);
474CHECK_SIZE_AND_OFFSET(shmid_ds, shm_segsz);
475CHECK_SIZE_AND_OFFSET(shmid_ds, shm_atime);
476CHECK_SIZE_AND_OFFSET(shmid_ds, shm_dtime);
477CHECK_SIZE_AND_OFFSET(shmid_ds, shm_ctime);
478CHECK_SIZE_AND_OFFSET(shmid_ds, shm_cpid);
479CHECK_SIZE_AND_OFFSET(shmid_ds, shm_lpid);
480CHECK_SIZE_AND_OFFSET(shmid_ds, shm_nattch);
481
482CHECK_TYPE_SIZE(clock_t);
483
484CHECK_TYPE_SIZE(ifaddrs);
485CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_next);
486CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_name);
487CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_addr);
488CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_netmask);
489#undef ifa_dstaddr
490CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_dstaddr);
491CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_data);
492
493CHECK_TYPE_SIZE(timeb);
494CHECK_SIZE_AND_OFFSET(timeb, time);
495CHECK_SIZE_AND_OFFSET(timeb, millitm);
496CHECK_SIZE_AND_OFFSET(timeb, timezone);
497CHECK_SIZE_AND_OFFSET(timeb, dstflag);
498
499CHECK_TYPE_SIZE(passwd);
500CHECK_SIZE_AND_OFFSET(passwd, pw_name);
501CHECK_SIZE_AND_OFFSET(passwd, pw_passwd);
502CHECK_SIZE_AND_OFFSET(passwd, pw_uid);
503CHECK_SIZE_AND_OFFSET(passwd, pw_gid);
504CHECK_SIZE_AND_OFFSET(passwd, pw_dir);
505CHECK_SIZE_AND_OFFSET(passwd, pw_shell);
506
507CHECK_SIZE_AND_OFFSET(passwd, pw_gecos);
508
509CHECK_TYPE_SIZE(group);
510CHECK_SIZE_AND_OFFSET(group, gr_name);
511CHECK_SIZE_AND_OFFSET(group, gr_passwd);
512CHECK_SIZE_AND_OFFSET(group, gr_gid);
513CHECK_SIZE_AND_OFFSET(group, gr_mem);
514
515#if HAVE_RPC_XDR_H
516CHECK_TYPE_SIZE(XDR);
517CHECK_SIZE_AND_OFFSET(XDR, x_op);
518CHECK_SIZE_AND_OFFSET(XDR, x_ops);
519CHECK_SIZE_AND_OFFSET(XDR, x_public);
520CHECK_SIZE_AND_OFFSET(XDR, x_private);
521CHECK_SIZE_AND_OFFSET(XDR, x_base);
522CHECK_SIZE_AND_OFFSET(XDR, x_handy);
523COMPILER_CHECK(__sanitizer_XDR_ENCODE == XDR_ENCODE);
524COMPILER_CHECK(__sanitizer_XDR_DECODE == XDR_DECODE);
525COMPILER_CHECK(__sanitizer_XDR_FREE == XDR_FREE);
526#endif
527
528CHECK_TYPE_SIZE(sem_t);
529
530COMPILER_CHECK(sizeof(__sanitizer_cap_rights_t) >= sizeof(cap_rights_t));
531#endif // SANITIZER_FREEBSD
lib/tsan/sanitizer_common/sanitizer_platform_limits_freebsd.h created+656
...@@ -0,0 +1,656 @@
1//===-- sanitizer_platform_limits_freebsd.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// Sizes and layouts of platform-specific FreeBSD data structures.
12//===----------------------------------------------------------------------===//
13
14#ifndef SANITIZER_PLATFORM_LIMITS_FREEBSD_H
15#define SANITIZER_PLATFORM_LIMITS_FREEBSD_H
16
17#if SANITIZER_FREEBSD
18
19#include "sanitizer_internal_defs.h"
20#include "sanitizer_platform.h"
21#include "sanitizer_platform_limits_posix.h"
22
23// Get sys/_types.h, because that tells us whether 64-bit inodes are
24// used in struct dirent below.
25#include <sys/_types.h>
26
27namespace __sanitizer {
28void *__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)
31
32extern unsigned struct_utsname_sz;
33extern unsigned struct_stat_sz;
34#if defined(__powerpc64__)
35const unsigned struct___old_kernel_stat_sz = 0;
36#else
37const unsigned struct___old_kernel_stat_sz = 32;
38#endif
39extern unsigned struct_rusage_sz;
40extern unsigned siginfo_t_sz;
41extern unsigned struct_itimerval_sz;
42extern unsigned pthread_t_sz;
43extern unsigned pthread_mutex_t_sz;
44extern unsigned pthread_cond_t_sz;
45extern unsigned pid_t_sz;
46extern unsigned timeval_sz;
47extern unsigned uid_t_sz;
48extern unsigned gid_t_sz;
49extern unsigned fpos_t_sz;
50extern unsigned mbstate_t_sz;
51extern unsigned struct_timezone_sz;
52extern unsigned struct_tms_sz;
53extern unsigned struct_itimerspec_sz;
54extern unsigned struct_sigevent_sz;
55extern unsigned struct_stack_t_sz;
56extern unsigned struct_sched_param_sz;
57extern unsigned struct_statfs64_sz;
58extern unsigned struct_statfs_sz;
59extern unsigned struct_sockaddr_sz;
60extern unsigned ucontext_t_sz;
61extern unsigned struct_rlimit_sz;
62extern unsigned struct_utimbuf_sz;
63extern unsigned struct_timespec_sz;
64extern unsigned struct_regmatch_sz;
65extern unsigned struct_regex_sz;
66extern unsigned struct_FTS_sz;
67extern unsigned struct_FTSENT_sz;
68extern const int unvis_valid;
69extern const int unvis_validpush;
70
71struct __sanitizer_iocb {
72 u64 aio_data;
73 u32 aio_key_or_aio_reserved1; // Simply crazy.
74 u32 aio_reserved1_or_aio_key; // Luckily, we don't need these.
75 u16 aio_lio_opcode;
76 s16 aio_reqprio;
77 u32 aio_fildes;
78 u64 aio_buf;
79 u64 aio_nbytes;
80 s64 aio_offset;
81 u64 aio_reserved2;
82 u64 aio_reserved3;
83};
84
85struct __sanitizer_io_event {
86 u64 data;
87 u64 obj;
88 u64 res;
89 u64 res2;
90};
91
92const unsigned iocb_cmd_pread = 0;
93const unsigned iocb_cmd_pwrite = 1;
94const unsigned iocb_cmd_preadv = 7;
95const unsigned iocb_cmd_pwritev = 8;
96
97struct __sanitizer___sysctl_args {
98 int *name;
99 int nlen;
100 void *oldval;
101 uptr *oldlenp;
102 void *newval;
103 uptr newlen;
104 unsigned long ___unused[4];
105};
106
107struct __sanitizer_ipc_perm {
108 unsigned int cuid;
109 unsigned int cgid;
110 unsigned int uid;
111 unsigned int gid;
112 unsigned short mode;
113 unsigned short seq;
114 long key;
115};
116
117#if !defined(__i386__)
118typedef long long __sanitizer_time_t;
119#else
120typedef long __sanitizer_time_t;
121#endif
122
123struct __sanitizer_shmid_ds {
124 __sanitizer_ipc_perm shm_perm;
125 unsigned long shm_segsz;
126 unsigned int shm_lpid;
127 unsigned int shm_cpid;
128 int shm_nattch;
129 __sanitizer_time_t shm_atime;
130 __sanitizer_time_t shm_dtime;
131 __sanitizer_time_t shm_ctime;
132};
133
134extern unsigned struct_msqid_ds_sz;
135extern unsigned struct_mq_attr_sz;
136extern unsigned struct_timeb_sz;
137extern unsigned struct_statvfs_sz;
138
139struct __sanitizer_iovec {
140 void *iov_base;
141 uptr iov_len;
142};
143
144struct __sanitizer_ifaddrs {
145 struct __sanitizer_ifaddrs *ifa_next;
146 char *ifa_name;
147 unsigned int ifa_flags;
148 void *ifa_addr; // (struct sockaddr *)
149 void *ifa_netmask; // (struct sockaddr *)
150#undef ifa_dstaddr
151 void *ifa_dstaddr; // (struct sockaddr *)
152 void *ifa_data;
153};
154
155typedef unsigned __sanitizer_pthread_key_t;
156
157struct __sanitizer_passwd {
158 char *pw_name;
159 char *pw_passwd;
160 int pw_uid;
161 int pw_gid;
162 __sanitizer_time_t pw_change;
163 char *pw_class;
164 char *pw_gecos;
165 char *pw_dir;
166 char *pw_shell;
167 __sanitizer_time_t pw_expire;
168 int pw_fields;
169};
170
171struct __sanitizer_group {
172 char *gr_name;
173 char *gr_passwd;
174 int gr_gid;
175 char **gr_mem;
176};
177
178typedef long __sanitizer_suseconds_t;
179
180struct __sanitizer_timeval {
181 __sanitizer_time_t tv_sec;
182 __sanitizer_suseconds_t tv_usec;
183};
184
185struct __sanitizer_itimerval {
186 struct __sanitizer_timeval it_interval;
187 struct __sanitizer_timeval it_value;
188};
189
190struct __sanitizer_timeb {
191 __sanitizer_time_t time;
192 unsigned short millitm;
193 short timezone;
194 short dstflag;
195};
196
197struct __sanitizer_ether_addr {
198 u8 octet[6];
199};
200
201struct __sanitizer_tm {
202 int tm_sec;
203 int tm_min;
204 int tm_hour;
205 int tm_mday;
206 int tm_mon;
207 int tm_year;
208 int tm_wday;
209 int tm_yday;
210 int tm_isdst;
211 long int tm_gmtoff;
212 const char *tm_zone;
213};
214
215struct __sanitizer_msghdr {
216 void *msg_name;
217 unsigned msg_namelen;
218 struct __sanitizer_iovec *msg_iov;
219 unsigned msg_iovlen;
220 void *msg_control;
221 unsigned msg_controllen;
222 int msg_flags;
223};
224
225struct __sanitizer_cmsghdr {
226 unsigned cmsg_len;
227 int cmsg_level;
228 int cmsg_type;
229};
230
231struct __sanitizer_dirent {
232#if defined(__INO64)
233 unsigned long long d_fileno;
234 unsigned long long d_off;
235#else
236 unsigned int d_fileno;
237#endif
238 unsigned short d_reclen;
239 // more fields that we don't care about
240};
241
242// 'clock_t' is 32 bits wide on x64 FreeBSD
243typedef int __sanitizer_clock_t;
244typedef int __sanitizer_clockid_t;
245
246#if defined(_LP64) || defined(__x86_64__) || defined(__powerpc__) || \
247 defined(__mips__)
248typedef unsigned __sanitizer___kernel_uid_t;
249typedef unsigned __sanitizer___kernel_gid_t;
250#else
251typedef unsigned short __sanitizer___kernel_uid_t;
252typedef unsigned short __sanitizer___kernel_gid_t;
253#endif
254typedef long long __sanitizer___kernel_off_t;
255
256#if defined(__powerpc__) || defined(__mips__)
257typedef unsigned int __sanitizer___kernel_old_uid_t;
258typedef unsigned int __sanitizer___kernel_old_gid_t;
259#else
260typedef unsigned short __sanitizer___kernel_old_uid_t;
261typedef unsigned short __sanitizer___kernel_old_gid_t;
262#endif
263
264typedef long long __sanitizer___kernel_loff_t;
265typedef struct {
266 unsigned long fds_bits[1024 / (8 * sizeof(long))];
267} __sanitizer___kernel_fd_set;
268
269// This thing depends on the platform. We are only interested in the upper
270// limit. Verified with a compiler assert in .cpp.
271union __sanitizer_pthread_attr_t {
272 char size[128];
273 void *align;
274};
275
276const unsigned old_sigset_t_sz = sizeof(unsigned long);
277
278struct __sanitizer_sigset_t {
279 // uint32_t * 4
280 unsigned int __bits[4];
281};
282
283typedef __sanitizer_sigset_t __sanitizer_kernel_sigset_t;
284
285struct __sanitizer_siginfo {
286 // The size is determined by looking at sizeof of real siginfo_t on linux.
287 u64 opaque[128 / sizeof(u64)];
288};
289
290using __sanitizer_sighandler_ptr = void (*)(int sig);
291using __sanitizer_sigactionhandler_ptr = void (*)(int sig,
292 __sanitizer_siginfo *siginfo,
293 void *uctx);
294
295struct __sanitizer_sigaction {
296 union {
297 __sanitizer_sigactionhandler_ptr sigaction;
298 __sanitizer_sighandler_ptr handler;
299 };
300 int sa_flags;
301 __sanitizer_sigset_t sa_mask;
302};
303
304struct __sanitizer_sem_t {
305 u32 data[4];
306};
307
308extern const uptr sig_ign;
309extern const uptr sig_dfl;
310extern const uptr sig_err;
311extern const uptr sa_siginfo;
312
313extern int af_inet;
314extern int af_inet6;
315uptr __sanitizer_in_addr_sz(int af);
316
317struct __sanitizer_dl_phdr_info {
318 uptr dlpi_addr;
319 const char *dlpi_name;
320 const void *dlpi_phdr;
321 short dlpi_phnum;
322};
323
324extern unsigned struct_ElfW_Phdr_sz;
325
326struct __sanitizer_addrinfo {
327 int ai_flags;
328 int ai_family;
329 int ai_socktype;
330 int ai_protocol;
331 unsigned ai_addrlen;
332 char *ai_canonname;
333 void *ai_addr;
334 struct __sanitizer_addrinfo *ai_next;
335};
336
337struct __sanitizer_hostent {
338 char *h_name;
339 char **h_aliases;
340 int h_addrtype;
341 int h_length;
342 char **h_addr_list;
343};
344
345struct __sanitizer_pollfd {
346 int fd;
347 short events;
348 short revents;
349};
350
351typedef unsigned __sanitizer_nfds_t;
352
353struct __sanitizer_glob_t {
354 uptr gl_pathc;
355 uptr gl_matchc;
356 uptr gl_offs;
357 int gl_flags;
358 char **gl_pathv;
359 int (*gl_errfunc)(const char *, int);
360 void (*gl_closedir)(void *dirp);
361 struct dirent *(*gl_readdir)(void *dirp);
362 void *(*gl_opendir)(const char *);
363 int (*gl_lstat)(const char *, void * /* struct stat* */);
364 int (*gl_stat)(const char *, void * /* struct stat* */);
365};
366
367extern int glob_nomatch;
368extern int glob_altdirfunc;
369
370extern unsigned path_max;
371
372struct __sanitizer_wordexp_t {
373 uptr we_wordc;
374 char **we_wordv;
375 uptr we_offs;
376 char *we_strings;
377 uptr we_nbytes;
378};
379
380typedef void __sanitizer_FILE;
381
382extern unsigned struct_shminfo_sz;
383extern unsigned struct_shm_info_sz;
384extern int shmctl_ipc_stat;
385extern int shmctl_ipc_info;
386extern int shmctl_shm_info;
387extern int shmctl_shm_stat;
388
389extern unsigned struct_utmpx_sz;
390
391extern int map_fixed;
392
393// ioctl arguments
394struct __sanitizer_ifconf {
395 int ifc_len;
396 union {
397 void *ifcu_req;
398 } ifc_ifcu;
399};
400
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)
434
435extern unsigned struct_ifreq_sz;
436extern unsigned struct_termios_sz;
437extern unsigned struct_winsize_sz;
438
439extern unsigned struct_copr_buffer_sz;
440extern unsigned struct_copr_debug_buf_sz;
441extern unsigned struct_copr_msg_sz;
442extern unsigned struct_midi_info_sz;
443extern unsigned struct_mtget_sz;
444extern unsigned struct_mtop_sz;
445extern unsigned struct_rtentry_sz;
446extern unsigned struct_sbi_instrument_sz;
447extern unsigned struct_seq_event_rec_sz;
448extern unsigned struct_synth_info_sz;
449extern unsigned struct_vt_mode_sz;
450
451extern const unsigned long __sanitizer_bufsiz;
452extern unsigned struct_audio_buf_info_sz;
453extern unsigned struct_ppp_stats_sz;
454extern unsigned struct_sioc_sg_req_sz;
455extern unsigned struct_sioc_vif_req_sz;
456
457// ioctl request identifiers
458
459// A special value to mark ioctls that are not present on the target platform,
460// when it can not be determined without including any system headers.
461extern const unsigned IOCTL_NOT_PRESENT;
462
463extern unsigned IOCTL_FIOASYNC;
464extern unsigned IOCTL_FIOCLEX;
465extern unsigned IOCTL_FIOGETOWN;
466extern unsigned IOCTL_FIONBIO;
467extern unsigned IOCTL_FIONCLEX;
468extern unsigned IOCTL_FIOSETOWN;
469extern unsigned IOCTL_SIOCADDMULTI;
470extern unsigned IOCTL_SIOCATMARK;
471extern unsigned IOCTL_SIOCDELMULTI;
472extern unsigned IOCTL_SIOCGIFADDR;
473extern unsigned IOCTL_SIOCGIFBRDADDR;
474extern unsigned IOCTL_SIOCGIFCONF;
475extern unsigned IOCTL_SIOCGIFDSTADDR;
476extern unsigned IOCTL_SIOCGIFFLAGS;
477extern unsigned IOCTL_SIOCGIFMETRIC;
478extern unsigned IOCTL_SIOCGIFMTU;
479extern unsigned IOCTL_SIOCGIFNETMASK;
480extern unsigned IOCTL_SIOCGPGRP;
481extern unsigned IOCTL_SIOCSIFADDR;
482extern unsigned IOCTL_SIOCSIFBRDADDR;
483extern unsigned IOCTL_SIOCSIFDSTADDR;
484extern unsigned IOCTL_SIOCSIFFLAGS;
485extern unsigned IOCTL_SIOCSIFMETRIC;
486extern unsigned IOCTL_SIOCSIFMTU;
487extern unsigned IOCTL_SIOCSIFNETMASK;
488extern unsigned IOCTL_SIOCSPGRP;
489extern unsigned IOCTL_TIOCCONS;
490extern unsigned IOCTL_TIOCEXCL;
491extern unsigned IOCTL_TIOCGETD;
492extern unsigned IOCTL_TIOCGPGRP;
493extern unsigned IOCTL_TIOCGWINSZ;
494extern unsigned IOCTL_TIOCMBIC;
495extern unsigned IOCTL_TIOCMBIS;
496extern unsigned IOCTL_TIOCMGET;
497extern unsigned IOCTL_TIOCMSET;
498extern unsigned IOCTL_TIOCNOTTY;
499extern unsigned IOCTL_TIOCNXCL;
500extern unsigned IOCTL_TIOCOUTQ;
501extern unsigned IOCTL_TIOCPKT;
502extern unsigned IOCTL_TIOCSCTTY;
503extern unsigned IOCTL_TIOCSETD;
504extern unsigned IOCTL_TIOCSPGRP;
505extern unsigned IOCTL_TIOCSTI;
506extern unsigned IOCTL_TIOCSWINSZ;
507extern unsigned IOCTL_SIOCGETSGCNT;
508extern unsigned IOCTL_SIOCGETVIFCNT;
509extern unsigned IOCTL_MTIOCGET;
510extern unsigned IOCTL_MTIOCTOP;
511extern unsigned IOCTL_SIOCADDRT;
512extern unsigned IOCTL_SIOCDELRT;
513extern unsigned IOCTL_SNDCTL_DSP_GETBLKSIZE;
514extern unsigned IOCTL_SNDCTL_DSP_GETFMTS;
515extern unsigned IOCTL_SNDCTL_DSP_NONBLOCK;
516extern unsigned IOCTL_SNDCTL_DSP_POST;
517extern unsigned IOCTL_SNDCTL_DSP_RESET;
518extern unsigned IOCTL_SNDCTL_DSP_SETFMT;
519extern unsigned IOCTL_SNDCTL_DSP_SETFRAGMENT;
520extern unsigned IOCTL_SNDCTL_DSP_SPEED;
521extern unsigned IOCTL_SNDCTL_DSP_STEREO;
522extern unsigned IOCTL_SNDCTL_DSP_SUBDIVIDE;
523extern unsigned IOCTL_SNDCTL_DSP_SYNC;
524extern unsigned IOCTL_SNDCTL_FM_4OP_ENABLE;
525extern unsigned IOCTL_SNDCTL_FM_LOAD_INSTR;
526extern unsigned IOCTL_SNDCTL_MIDI_INFO;
527extern unsigned IOCTL_SNDCTL_MIDI_PRETIME;
528extern unsigned IOCTL_SNDCTL_SEQ_CTRLRATE;
529extern unsigned IOCTL_SNDCTL_SEQ_GETINCOUNT;
530extern unsigned IOCTL_SNDCTL_SEQ_GETOUTCOUNT;
531extern unsigned IOCTL_SNDCTL_SEQ_NRMIDIS;
532extern unsigned IOCTL_SNDCTL_SEQ_NRSYNTHS;
533extern unsigned IOCTL_SNDCTL_SEQ_OUTOFBAND;
534extern unsigned IOCTL_SNDCTL_SEQ_PANIC;
535extern unsigned IOCTL_SNDCTL_SEQ_PERCMODE;
536extern unsigned IOCTL_SNDCTL_SEQ_RESET;
537extern unsigned IOCTL_SNDCTL_SEQ_RESETSAMPLES;
538extern unsigned IOCTL_SNDCTL_SEQ_SYNC;
539extern unsigned IOCTL_SNDCTL_SEQ_TESTMIDI;
540extern unsigned IOCTL_SNDCTL_SEQ_THRESHOLD;
541extern unsigned IOCTL_SNDCTL_SYNTH_INFO;
542extern unsigned IOCTL_SNDCTL_SYNTH_MEMAVL;
543extern unsigned IOCTL_SNDCTL_TMR_CONTINUE;
544extern unsigned IOCTL_SNDCTL_TMR_METRONOME;
545extern unsigned IOCTL_SNDCTL_TMR_SELECT;
546extern unsigned IOCTL_SNDCTL_TMR_SOURCE;
547extern unsigned IOCTL_SNDCTL_TMR_START;
548extern unsigned IOCTL_SNDCTL_TMR_STOP;
549extern unsigned IOCTL_SNDCTL_TMR_TEMPO;
550extern unsigned IOCTL_SNDCTL_TMR_TIMEBASE;
551extern unsigned IOCTL_SOUND_MIXER_READ_ALTPCM;
552extern unsigned IOCTL_SOUND_MIXER_READ_BASS;
553extern unsigned IOCTL_SOUND_MIXER_READ_CAPS;
554extern unsigned IOCTL_SOUND_MIXER_READ_CD;
555extern unsigned IOCTL_SOUND_MIXER_READ_DEVMASK;
556extern unsigned IOCTL_SOUND_MIXER_READ_ENHANCE;
557extern unsigned IOCTL_SOUND_MIXER_READ_IGAIN;
558extern unsigned IOCTL_SOUND_MIXER_READ_IMIX;
559extern unsigned IOCTL_SOUND_MIXER_READ_LINE1;
560extern unsigned IOCTL_SOUND_MIXER_READ_LINE2;
561extern unsigned IOCTL_SOUND_MIXER_READ_LINE3;
562extern unsigned IOCTL_SOUND_MIXER_READ_LINE;
563extern unsigned IOCTL_SOUND_MIXER_READ_LOUD;
564extern unsigned IOCTL_SOUND_MIXER_READ_MIC;
565extern unsigned IOCTL_SOUND_MIXER_READ_MUTE;
566extern unsigned IOCTL_SOUND_MIXER_READ_OGAIN;
567extern unsigned IOCTL_SOUND_MIXER_READ_PCM;
568extern unsigned IOCTL_SOUND_MIXER_READ_RECLEV;
569extern unsigned IOCTL_SOUND_MIXER_READ_RECMASK;
570extern unsigned IOCTL_SOUND_MIXER_READ_RECSRC;
571extern unsigned IOCTL_SOUND_MIXER_READ_SPEAKER;
572extern unsigned IOCTL_SOUND_MIXER_READ_STEREODEVS;
573extern unsigned IOCTL_SOUND_MIXER_READ_SYNTH;
574extern unsigned IOCTL_SOUND_MIXER_READ_TREBLE;
575extern unsigned IOCTL_SOUND_MIXER_READ_VOLUME;
576extern unsigned IOCTL_SOUND_MIXER_WRITE_ALTPCM;
577extern unsigned IOCTL_SOUND_MIXER_WRITE_BASS;
578extern unsigned IOCTL_SOUND_MIXER_WRITE_CD;
579extern unsigned IOCTL_SOUND_MIXER_WRITE_ENHANCE;
580extern unsigned IOCTL_SOUND_MIXER_WRITE_IGAIN;
581extern unsigned IOCTL_SOUND_MIXER_WRITE_IMIX;
582extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE1;
583extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE2;
584extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE3;
585extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE;
586extern unsigned IOCTL_SOUND_MIXER_WRITE_LOUD;
587extern unsigned IOCTL_SOUND_MIXER_WRITE_MIC;
588extern unsigned IOCTL_SOUND_MIXER_WRITE_MUTE;
589extern unsigned IOCTL_SOUND_MIXER_WRITE_OGAIN;
590extern unsigned IOCTL_SOUND_MIXER_WRITE_PCM;
591extern unsigned IOCTL_SOUND_MIXER_WRITE_RECLEV;
592extern unsigned IOCTL_SOUND_MIXER_WRITE_RECSRC;
593extern unsigned IOCTL_SOUND_MIXER_WRITE_SPEAKER;
594extern unsigned IOCTL_SOUND_MIXER_WRITE_SYNTH;
595extern unsigned IOCTL_SOUND_MIXER_WRITE_TREBLE;
596extern unsigned IOCTL_SOUND_MIXER_WRITE_VOLUME;
597extern unsigned IOCTL_SOUND_PCM_READ_BITS;
598extern unsigned IOCTL_SOUND_PCM_READ_CHANNELS;
599extern unsigned IOCTL_SOUND_PCM_READ_FILTER;
600extern unsigned IOCTL_SOUND_PCM_READ_RATE;
601extern unsigned IOCTL_SOUND_PCM_WRITE_CHANNELS;
602extern unsigned IOCTL_SOUND_PCM_WRITE_FILTER;
603extern unsigned IOCTL_VT_ACTIVATE;
604extern unsigned IOCTL_VT_GETMODE;
605extern unsigned IOCTL_VT_OPENQRY;
606extern unsigned IOCTL_VT_RELDISP;
607extern unsigned IOCTL_VT_SETMODE;
608extern unsigned IOCTL_VT_WAITACTIVE;
609extern unsigned IOCTL_GIO_SCRNMAP;
610extern unsigned IOCTL_KDDISABIO;
611extern unsigned IOCTL_KDENABIO;
612extern unsigned IOCTL_KDGETLED;
613extern unsigned IOCTL_KDGETMODE;
614extern unsigned IOCTL_KDGKBMODE;
615extern unsigned IOCTL_KDGKBTYPE;
616extern unsigned IOCTL_KDMKTONE;
617extern unsigned IOCTL_KDSETLED;
618extern unsigned IOCTL_KDSETMODE;
619extern unsigned IOCTL_KDSKBMODE;
620
621extern const int si_SEGV_MAPERR;
622extern const int si_SEGV_ACCERR;
623
624struct __sanitizer_cap_rights {
625 u64 cr_rights[2];
626};
627
628typedef struct __sanitizer_cap_rights __sanitizer_cap_rights_t;
629extern unsigned struct_cap_rights_sz;
630
631extern unsigned struct_fstab_sz;
632extern unsigned struct_StringList_sz;
633} // namespace __sanitizer
634
635#define CHECK_TYPE_SIZE(TYPE) \
636 COMPILER_CHECK(sizeof(__sanitizer_##TYPE) == sizeof(TYPE))
637
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))
643
644// For sigaction, which is a function and struct at the same time,
645// 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))
651
652#define SIGACTION_SYMNAME sigaction
653
654#endif
655
656#endif // SANITIZER_FREEBSD
lib/tsan/sanitizer_common/sanitizer_platform_limits_linux.cpp created+108
...@@ -0,0 +1,108 @@
1//===-- sanitizer_platform_limits_linux.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 Sanitizer common code.
10//
11// Sizes and layouts of linux kernel data structures.
12//===----------------------------------------------------------------------===//
13
14// This is a separate compilation unit for linux headers that conflict with
15// userspace headers.
16// Most "normal" includes go in sanitizer_platform_limits_posix.cpp
17
18#include "sanitizer_platform.h"
19#if SANITIZER_LINUX
20
21#include "sanitizer_internal_defs.h"
22#include "sanitizer_platform_limits_posix.h"
23
24// For offsetof -> __builtin_offsetof definition.
25#include <stddef.h>
26
27// With old kernels (and even new kernels on powerpc) asm/stat.h uses types that
28// are not defined anywhere in userspace headers. Fake them. This seems to work
29// fine with newer headers, too.
30#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
41// 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
57
58using namespace __sanitizer;
59
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)
69COMPILER_CHECK(struct___old_kernel_stat_sz == sizeof(struct __old_kernel_stat));
70#endif
71
72COMPILER_CHECK(struct_kernel_stat_sz == sizeof(struct stat));
73
74#if defined(__i386__)
75COMPILER_CHECK(struct_kernel_stat64_sz == sizeof(struct stat64));
76#endif
77
78CHECK_TYPE_SIZE(io_event);
79CHECK_SIZE_AND_OFFSET(io_event, data);
80CHECK_SIZE_AND_OFFSET(io_event, obj);
81CHECK_SIZE_AND_OFFSET(io_event, res);
82CHECK_SIZE_AND_OFFSET(io_event, res2);
83
84#if !SANITIZER_ANDROID
85COMPILER_CHECK(sizeof(struct __sanitizer_perf_event_attr) <=
86 sizeof(struct perf_event_attr));
87CHECK_SIZE_AND_OFFSET(perf_event_attr, type);
88CHECK_SIZE_AND_OFFSET(perf_event_attr, size);
89#endif
90
91COMPILER_CHECK(iocb_cmd_pread == IOCB_CMD_PREAD);
92COMPILER_CHECK(iocb_cmd_pwrite == IOCB_CMD_PWRITE);
93#if !SANITIZER_ANDROID
94COMPILER_CHECK(iocb_cmd_preadv == IOCB_CMD_PREADV);
95COMPILER_CHECK(iocb_cmd_pwritev == IOCB_CMD_PWRITEV);
96#endif
97
98CHECK_TYPE_SIZE(iocb);
99CHECK_SIZE_AND_OFFSET(iocb, aio_data);
100// Skip aio_key, it's weird.
101CHECK_SIZE_AND_OFFSET(iocb, aio_lio_opcode);
102CHECK_SIZE_AND_OFFSET(iocb, aio_reqprio);
103CHECK_SIZE_AND_OFFSET(iocb, aio_fildes);
104CHECK_SIZE_AND_OFFSET(iocb, aio_buf);
105CHECK_SIZE_AND_OFFSET(iocb, aio_nbytes);
106CHECK_SIZE_AND_OFFSET(iocb, aio_offset);
107
108#endif // SANITIZER_LINUX
lib/tsan/sanitizer_common/sanitizer_platform_limits_netbsd.cpp created+2586
...@@ -0,0 +1,2586 @@
1//===-- sanitizer_platform_limits_netbsd.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 Sanitizer common code.
10//
11// Sizes and layouts of platform-specific NetBSD data structures.
12//===----------------------------------------------------------------------===//
13
14#include "sanitizer_platform.h"
15
16#if SANITIZER_NETBSD
17
18#define _KMEMUSER
19#define RAY_DO_SIGLEV
20#define __LEGACY_PT_LWPINFO
21
22// clang-format off
23#include <sys/param.h>
24#include <sys/types.h>
25#include <sys/sysctl.h>
26#include <sys/disk.h>
27#include <sys/disklabel.h>
28#include <sys/mount.h>
29#include <sys/agpio.h>
30#include <sys/ataio.h>
31#include <sys/audioio.h>
32#include <sys/cdbr.h>
33#include <sys/cdio.h>
34#include <sys/chio.h>
35#include <sys/clockctl.h>
36#include <sys/cpuio.h>
37#include <sys/dkio.h>
38#include <sys/drvctlio.h>
39#include <sys/dvdio.h>
40#include <sys/envsys.h>
41#include <sys/event.h>
42#include <sys/fdio.h>
43#include <sys/filio.h>
44#include <sys/gpio.h>
45#include <sys/ioctl.h>
46#include <sys/ioctl_compat.h>
47#include <sys/joystick.h>
48#include <sys/ksyms.h>
49#include <sys/lua.h>
50#include <sys/midiio.h>
51#include <sys/mtio.h>
52#include <sys/power.h>
53#include <sys/radioio.h>
54#include <sys/rndio.h>
55#include <sys/scanio.h>
56#include <sys/scsiio.h>
57#include <sys/sockio.h>
58#include <sys/timepps.h>
59#include <sys/ttycom.h>
60#include <sys/verified_exec.h>
61#include <sys/videoio.h>
62#include <sys/wdog.h>
63#include <sys/event.h>
64#include <sys/filio.h>
65#include <sys/ipc.h>
66#include <sys/ipmi.h>
67#include <sys/kcov.h>
68#include <sys/mman.h>
69#include <sys/module.h>
70#include <sys/mount.h>
71#include <sys/mqueue.h>
72#include <sys/msg.h>
73#include <sys/mtio.h>
74#include <sys/ptrace.h>
75
76// Compat for NetBSD < 9.99.30.
77#ifndef PT_LWPSTATUS
78#define PT_LWPSTATUS 24
79#endif
80#ifndef PT_LWPNEXT
81#define PT_LWPNEXT 25
82#endif
83
84#include <sys/resource.h>
85#include <sys/sem.h>
86#include <sys/sha1.h>
87#include <sys/sha2.h>
88#include <sys/shm.h>
89#include <sys/signal.h>
90#include <sys/socket.h>
91#include <sys/sockio.h>
92#include <sys/soundcard.h>
93#include <sys/stat.h>
94#include <sys/statvfs.h>
95#include <sys/time.h>
96#include <sys/timeb.h>
97#include <sys/times.h>
98#include <sys/timespec.h>
99#include <sys/timex.h>
100#include <sys/types.h>
101#include <sys/ucontext.h>
102#include <sys/utsname.h>
103#include <altq/altq.h>
104#include <altq/altq_afmap.h>
105#include <altq/altq_blue.h>
106#include <altq/altq_cbq.h>
107#include <altq/altq_cdnr.h>
108#include <altq/altq_fifoq.h>
109#include <altq/altq_hfsc.h>
110#include <altq/altq_jobs.h>
111#include <altq/altq_priq.h>
112#include <altq/altq_red.h>
113#include <altq/altq_rio.h>
114#include <altq/altq_wfq.h>
115#include <arpa/inet.h>
116#include <crypto/cryptodev.h>
117#include <dev/apm/apmio.h>
118#include <dev/dm/netbsd-dm.h>
119#include <dev/dmover/dmover_io.h>
120#include <dev/dtv/dtvio_demux.h>
121#include <dev/dtv/dtvio_frontend.h>
122#if !__NetBSD_Prereq__(9, 99, 26)
123#include <dev/filemon/filemon.h>
124#else
125#define FILEMON_SET_FD _IOWR('S', 1, int)
126#define FILEMON_SET_PID _IOWR('S', 2, pid_t)
127#endif
128#include <dev/hdaudio/hdaudioio.h>
129#include <dev/hdmicec/hdmicecio.h>
130#include <dev/hpc/hpcfbio.h>
131#include <dev/i2o/iopio.h>
132#include <dev/ic/athioctl.h>
133#include <dev/ic/bt8xx.h>
134#include <dev/ic/icp_ioctl.h>
135#include <dev/ic/isp_ioctl.h>
136#include <dev/ic/mlxio.h>
137#include <dev/ic/qemufwcfgio.h>
138#include <dev/ic/nvmeio.h>
139#include <dev/ir/irdaio.h>
140#include <dev/isa/isvio.h>
141#include <dev/isa/wtreg.h>
142#include <dev/iscsi/iscsi_ioctl.h>
143#include <dev/ofw/openfirmio.h>
144#include <dev/pci/amrio.h>
145#include <dev/pci/mlyreg.h>
146#include <dev/pci/mlyio.h>
147#include <dev/pci/pciio.h>
148#include <dev/pci/tweio.h>
149#include <dev/pcmcia/if_cnwioctl.h>
150#include <net/bpf.h>
151#include <net/if_gre.h>
152#include <net/ppp_defs.h>
153#include <net/if_ppp.h>
154#include <net/if_pppoe.h>
155#include <net/if_sppp.h>
156#include <net/if_srt.h>
157#include <net/if_tap.h>
158#include <net/if_tun.h>
159#include <net/npf.h>
160#include <net/pfvar.h>
161#include <net/slip.h>
162#include <netbt/hci.h>
163#include <netinet/ip_compat.h>
164#if __has_include(<netinet/ip_fil.h>)
165#include <netinet/ip_fil.h>
166#include <netinet/ip_nat.h>
167#include <netinet/ip_proxy.h>
168#else
169/* Fallback for MKIPFILTER=no */
170
171typedef struct ap_control {
172 char apc_label[16];
173 char apc_config[16];
174 unsigned char apc_p;
175 unsigned long apc_cmd;
176 unsigned long apc_arg;
177 void *apc_data;
178 size_t apc_dsize;
179} ap_ctl_t;
180
181typedef struct ipftq {
182 ipfmutex_t ifq_lock;
183 unsigned int ifq_ttl;
184 void *ifq_head;
185 void **ifq_tail;
186 void *ifq_next;
187 void **ifq_pnext;
188 int ifq_ref;
189 unsigned int ifq_flags;
190} ipftq_t;
191
192typedef struct ipfobj {
193 uint32_t ipfo_rev;
194 uint32_t ipfo_size;
195 void *ipfo_ptr;
196 int ipfo_type;
197 int ipfo_offset;
198 int ipfo_retval;
199 unsigned char ipfo_xxxpad[28];
200} ipfobj_t;
201
202#define SIOCADNAT _IOW('r', 60, struct ipfobj)
203#define SIOCRMNAT _IOW('r', 61, struct ipfobj)
204#define SIOCGNATS _IOWR('r', 62, struct ipfobj)
205#define SIOCGNATL _IOWR('r', 63, struct ipfobj)
206#define SIOCPURGENAT _IOWR('r', 100, struct ipfobj)
207#endif
208#include <netinet6/in6_var.h>
209#include <netinet6/nd6.h>
210#if !__NetBSD_Prereq__(9, 99, 51)
211#include <netsmb/smb_dev.h>
212#else
213struct smbioc_flags {
214 int ioc_level;
215 int ioc_mask;
216 int ioc_flags;
217};
218struct smbioc_oshare {
219 int ioc_opt;
220 int ioc_stype;
221 char ioc_share[129];
222 char ioc_password[129];
223 uid_t ioc_owner;
224 gid_t ioc_group;
225 mode_t ioc_mode;
226 mode_t ioc_rights;
227};
228struct smbioc_ossn {
229 int ioc_opt;
230 uint32_t ioc_svlen;
231 struct sockaddr *ioc_server;
232 uint32_t ioc_lolen;
233 struct sockaddr *ioc_local;
234 char ioc_srvname[16];
235 int ioc_timeout;
236 int ioc_retrycount;
237 char ioc_localcs[16];
238 char ioc_servercs[16];
239 char ioc_user[129];
240 char ioc_workgroup[129];
241 char ioc_password[129];
242 uid_t ioc_owner;
243 gid_t ioc_group;
244 mode_t ioc_mode;
245 mode_t ioc_rights;
246};
247struct smbioc_lookup {
248 int ioc_level;
249 int ioc_flags;
250 struct smbioc_ossn ioc_ssn;
251 struct smbioc_oshare ioc_sh;
252};
253struct smbioc_rq {
254 u_char ioc_cmd;
255 u_char ioc_twc;
256 void *ioc_twords;
257 u_short ioc_tbc;
258 void *ioc_tbytes;
259 int ioc_rpbufsz;
260 char *ioc_rpbuf;
261 u_char ioc_rwc;
262 u_short ioc_rbc;
263};
264struct smbioc_rw {
265 u_int16_t ioc_fh;
266 char *ioc_base;
267 off_t ioc_offset;
268 int ioc_cnt;
269};
270#define SMBIOC_OPENSESSION _IOW('n', 100, struct smbioc_ossn)
271#define SMBIOC_OPENSHARE _IOW('n', 101, struct smbioc_oshare)
272#define SMBIOC_REQUEST _IOWR('n', 102, struct smbioc_rq)
273#define SMBIOC_T2RQ _IOWR('n', 103, struct smbioc_t2rq)
274#define SMBIOC_SETFLAGS _IOW('n', 104, struct smbioc_flags)
275#define SMBIOC_LOOKUP _IOW('n', 106, struct smbioc_lookup)
276#define SMBIOC_READ _IOWR('n', 107, struct smbioc_rw)
277#define SMBIOC_WRITE _IOWR('n', 108, struct smbioc_rw)
278#endif
279#include <dev/biovar.h>
280#include <dev/bluetooth/btdev.h>
281#include <dev/bluetooth/btsco.h>
282#include <dev/ccdvar.h>
283#include <dev/cgdvar.h>
284#include <dev/fssvar.h>
285#include <dev/kttcpio.h>
286#include <dev/lockstat.h>
287#include <dev/md.h>
288#include <net/if_ether.h>
289#include <dev/pcmcia/if_rayreg.h>
290#include <stdio.h>
291#include <dev/raidframe/raidframeio.h>
292#include <dev/sbus/mbppio.h>
293#include <dev/scsipi/ses.h>
294#include <dev/spi/spi_io.h>
295#include <dev/spkrio.h>
296#include <dev/sun/disklabel.h>
297#include <dev/sun/fbio.h>
298#include <dev/sun/kbio.h>
299#include <dev/sun/vuid_event.h>
300#include <dev/tc/sticio.h>
301#include <dev/usb/ukyopon.h>
302#if !__NetBSD_Prereq__(9, 99, 44)
303#include <dev/usb/urio.h>
304#else
305struct urio_command {
306 unsigned short length;
307 int request;
308 int requesttype;
309 int value;
310 int index;
311 void *buffer;
312 int timeout;
313};
314#define URIO_SEND_COMMAND _IOWR('U', 200, struct urio_command)
315#define URIO_RECV_COMMAND _IOWR('U', 201, struct urio_command)
316#endif
317#include <dev/usb/usb.h>
318#include <dev/usb/utoppy.h>
319#include <dev/vme/xio.h>
320#include <dev/vndvar.h>
321#include <dev/wscons/wsconsio.h>
322#include <dev/wscons/wsdisplay_usl_io.h>
323#include <fs/autofs/autofs_ioctl.h>
324#include <dirent.h>
325#include <dlfcn.h>
326#include <glob.h>
327#include <grp.h>
328#include <ifaddrs.h>
329#include <limits.h>
330#include <link_elf.h>
331#include <net/if.h>
332#include <net/route.h>
333#include <netdb.h>
334#include <netinet/in.h>
335#include <netinet/ip_mroute.h>
336#include <netinet/sctp_uio.h>
337#include <poll.h>
338#include <pthread.h>
339#include <pwd.h>
340#include <semaphore.h>
341#include <signal.h>
342#include <stddef.h>
343#include <md2.h>
344#include <md4.h>
345#include <md5.h>
346#include <rmd160.h>
347#include <soundcard.h>
348#include <term.h>
349#include <termios.h>
350#include <time.h>
351#include <ttyent.h>
352#include <utime.h>
353#include <utmp.h>
354#include <utmpx.h>
355#include <vis.h>
356#include <wchar.h>
357#include <wordexp.h>
358#include <ttyent.h>
359#include <fts.h>
360#include <regex.h>
361#include <fstab.h>
362#include <stringlist.h>
363
364#if defined(__x86_64__)
365#include <nvmm.h>
366#endif
367// clang-format on
368
369// Include these after system headers to avoid name clashes and ambiguities.
370#include "sanitizer_internal_defs.h"
371#include "sanitizer_libc.h"
372#include "sanitizer_platform_limits_netbsd.h"
373
374namespace __sanitizer {
375void *__sanitizer_get_link_map_by_dlopen_handle(void* handle) {
376 void *p = nullptr;
377 return internal_dlinfo(handle, RTLD_DI_LINKMAP, &p) == 0 ? p : nullptr;
378}
379
380unsigned struct_utsname_sz = sizeof(struct utsname);
381unsigned struct_stat_sz = sizeof(struct stat);
382unsigned struct_rusage_sz = sizeof(struct rusage);
383unsigned struct_tm_sz = sizeof(struct tm);
384unsigned struct_passwd_sz = sizeof(struct passwd);
385unsigned struct_group_sz = sizeof(struct group);
386unsigned siginfo_t_sz = sizeof(siginfo_t);
387unsigned struct_sigaction_sz = sizeof(struct sigaction);
388unsigned struct_stack_t_sz = sizeof(stack_t);
389unsigned struct_itimerval_sz = sizeof(struct itimerval);
390unsigned pthread_t_sz = sizeof(pthread_t);
391unsigned pthread_mutex_t_sz = sizeof(pthread_mutex_t);
392unsigned pthread_cond_t_sz = sizeof(pthread_cond_t);
393unsigned pid_t_sz = sizeof(pid_t);
394unsigned timeval_sz = sizeof(timeval);
395unsigned uid_t_sz = sizeof(uid_t);
396unsigned gid_t_sz = sizeof(gid_t);
397unsigned mbstate_t_sz = sizeof(mbstate_t);
398unsigned sigset_t_sz = sizeof(sigset_t);
399unsigned struct_timezone_sz = sizeof(struct timezone);
400unsigned struct_tms_sz = sizeof(struct tms);
401unsigned struct_sigevent_sz = sizeof(struct sigevent);
402unsigned struct_sched_param_sz = sizeof(struct sched_param);
403unsigned struct_sockaddr_sz = sizeof(struct sockaddr);
404unsigned ucontext_t_sz = sizeof(ucontext_t);
405unsigned struct_rlimit_sz = sizeof(struct rlimit);
406unsigned struct_timespec_sz = sizeof(struct timespec);
407unsigned struct_sembuf_sz = sizeof(struct sembuf);
408unsigned struct_kevent_sz = sizeof(struct kevent);
409unsigned struct_FTS_sz = sizeof(FTS);
410unsigned struct_FTSENT_sz = sizeof(FTSENT);
411unsigned struct_regex_sz = sizeof(regex_t);
412unsigned struct_regmatch_sz = sizeof(regmatch_t);
413unsigned struct_fstab_sz = sizeof(struct fstab);
414unsigned struct_utimbuf_sz = sizeof(struct utimbuf);
415unsigned struct_itimerspec_sz = sizeof(struct itimerspec);
416unsigned struct_timex_sz = sizeof(struct timex);
417unsigned struct_msqid_ds_sz = sizeof(struct msqid_ds);
418unsigned struct_mq_attr_sz = sizeof(struct mq_attr);
419unsigned struct_statvfs_sz = sizeof(struct statvfs);
420unsigned struct_sigaltstack_sz = sizeof(stack_t);
421
422const uptr sig_ign = (uptr)SIG_IGN;
423const uptr sig_dfl = (uptr)SIG_DFL;
424const uptr sig_err = (uptr)SIG_ERR;
425const uptr sa_siginfo = (uptr)SA_SIGINFO;
426
427const unsigned long __sanitizer_bufsiz = BUFSIZ;
428
429int ptrace_pt_io = PT_IO;
430int ptrace_pt_lwpinfo = PT_LWPINFO;
431int ptrace_pt_set_event_mask = PT_SET_EVENT_MASK;
432int ptrace_pt_get_event_mask = PT_GET_EVENT_MASK;
433int ptrace_pt_get_process_state = PT_GET_PROCESS_STATE;
434int ptrace_pt_set_siginfo = PT_SET_SIGINFO;
435int ptrace_pt_get_siginfo = PT_GET_SIGINFO;
436int ptrace_pt_lwpstatus = PT_LWPSTATUS;
437int ptrace_pt_lwpnext = PT_LWPNEXT;
438int ptrace_piod_read_d = PIOD_READ_D;
439int ptrace_piod_write_d = PIOD_WRITE_D;
440int ptrace_piod_read_i = PIOD_READ_I;
441int ptrace_piod_write_i = PIOD_WRITE_I;
442int ptrace_piod_read_auxv = PIOD_READ_AUXV;
443
444#if defined(PT_SETREGS) && defined(PT_GETREGS)
445int ptrace_pt_setregs = PT_SETREGS;
446int ptrace_pt_getregs = PT_GETREGS;
447#else
448int ptrace_pt_setregs = -1;
449int ptrace_pt_getregs = -1;
450#endif
451
452#if defined(PT_SETFPREGS) && defined(PT_GETFPREGS)
453int ptrace_pt_setfpregs = PT_SETFPREGS;
454int ptrace_pt_getfpregs = PT_GETFPREGS;
455#else
456int ptrace_pt_setfpregs = -1;
457int ptrace_pt_getfpregs = -1;
458#endif
459
460#if defined(PT_SETDBREGS) && defined(PT_GETDBREGS)
461int ptrace_pt_setdbregs = PT_SETDBREGS;
462int ptrace_pt_getdbregs = PT_GETDBREGS;
463#else
464int ptrace_pt_setdbregs = -1;
465int ptrace_pt_getdbregs = -1;
466#endif
467
468unsigned struct_ptrace_ptrace_io_desc_struct_sz = sizeof(struct ptrace_io_desc);
469unsigned struct_ptrace_ptrace_lwpinfo_struct_sz = sizeof(struct ptrace_lwpinfo);
470unsigned struct_ptrace_ptrace_lwpstatus_struct_sz =
471 sizeof(struct __sanitizer_ptrace_lwpstatus);
472unsigned struct_ptrace_ptrace_event_struct_sz = sizeof(ptrace_event_t);
473unsigned struct_ptrace_ptrace_siginfo_struct_sz = sizeof(ptrace_siginfo_t);
474
475#if defined(PT_SETREGS)
476unsigned struct_ptrace_reg_struct_sz = sizeof(struct reg);
477#else
478unsigned struct_ptrace_reg_struct_sz = -1;
479#endif
480
481#if defined(PT_SETFPREGS)
482unsigned struct_ptrace_fpreg_struct_sz = sizeof(struct fpreg);
483#else
484unsigned struct_ptrace_fpreg_struct_sz = -1;
485#endif
486
487#if defined(PT_SETDBREGS)
488unsigned struct_ptrace_dbreg_struct_sz = sizeof(struct dbreg);
489#else
490unsigned struct_ptrace_dbreg_struct_sz = -1;
491#endif
492
493int shmctl_ipc_stat = (int)IPC_STAT;
494
495unsigned struct_utmp_sz = sizeof(struct utmp);
496unsigned struct_utmpx_sz = sizeof(struct utmpx);
497
498int map_fixed = MAP_FIXED;
499
500int af_inet = (int)AF_INET;
501int af_inet6 = (int)AF_INET6;
502
503uptr __sanitizer_in_addr_sz(int af) {
504 if (af == AF_INET)
505 return sizeof(struct in_addr);
506 else if (af == AF_INET6)
507 return sizeof(struct in6_addr);
508 else
509 return 0;
510}
511
512unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
513
514int glob_nomatch = GLOB_NOMATCH;
515int glob_altdirfunc = GLOB_ALTDIRFUNC;
516
517unsigned path_max = PATH_MAX;
518
519int struct_ttyent_sz = sizeof(struct ttyent);
520
521struct __sanitizer_nvlist_ref_t {
522 void *buf;
523 uptr len;
524 int flags;
525};
526
527typedef __sanitizer_nvlist_ref_t nvlist_ref_t;
528
529// ioctl arguments
530unsigned struct_altqreq_sz = sizeof(altqreq);
531unsigned struct_amr_user_ioctl_sz = sizeof(amr_user_ioctl);
532unsigned struct_ap_control_sz = sizeof(ap_control);
533unsigned struct_apm_ctl_sz = sizeof(apm_ctl);
534unsigned struct_apm_event_info_sz = sizeof(apm_event_info);
535unsigned struct_apm_power_info_sz = sizeof(apm_power_info);
536unsigned struct_atabusiodetach_args_sz = sizeof(atabusiodetach_args);
537unsigned struct_atabusioscan_args_sz = sizeof(atabusioscan_args);
538unsigned struct_ath_diag_sz = sizeof(ath_diag);
539unsigned struct_atm_flowmap_sz = sizeof(atm_flowmap);
540unsigned struct_audio_buf_info_sz = sizeof(audio_buf_info);
541unsigned struct_audio_device_sz = sizeof(audio_device);
542unsigned struct_audio_encoding_sz = sizeof(audio_encoding);
543unsigned struct_audio_info_sz = sizeof(audio_info);
544unsigned struct_audio_offset_sz = sizeof(audio_offset);
545unsigned struct_bio_locate_sz = sizeof(bio_locate);
546unsigned struct_bioc_alarm_sz = sizeof(bioc_alarm);
547unsigned struct_bioc_blink_sz = sizeof(bioc_blink);
548unsigned struct_bioc_disk_sz = sizeof(bioc_disk);
549unsigned struct_bioc_inq_sz = sizeof(bioc_inq);
550unsigned struct_bioc_setstate_sz = sizeof(bioc_setstate);
551unsigned struct_bioc_vol_sz = sizeof(bioc_vol);
552unsigned struct_bioc_volops_sz = sizeof(bioc_volops);
553unsigned struct_bktr_chnlset_sz = sizeof(bktr_chnlset);
554unsigned struct_bktr_remote_sz = sizeof(bktr_remote);
555unsigned struct_blue_conf_sz = sizeof(blue_conf);
556unsigned struct_blue_interface_sz = sizeof(blue_interface);
557unsigned struct_blue_stats_sz = sizeof(blue_stats);
558unsigned struct_bpf_dltlist_sz = sizeof(bpf_dltlist);
559unsigned struct_bpf_program_sz = sizeof(bpf_program);
560unsigned struct_bpf_stat_old_sz = sizeof(bpf_stat_old);
561unsigned struct_bpf_stat_sz = sizeof(bpf_stat);
562unsigned struct_bpf_version_sz = sizeof(bpf_version);
563unsigned struct_btreq_sz = sizeof(btreq);
564unsigned struct_btsco_info_sz = sizeof(btsco_info);
565unsigned struct_buffmem_desc_sz = sizeof(buffmem_desc);
566unsigned struct_cbq_add_class_sz = sizeof(cbq_add_class);
567unsigned struct_cbq_add_filter_sz = sizeof(cbq_add_filter);
568unsigned struct_cbq_delete_class_sz = sizeof(cbq_delete_class);
569unsigned struct_cbq_delete_filter_sz = sizeof(cbq_delete_filter);
570unsigned struct_cbq_getstats_sz = sizeof(cbq_getstats);
571unsigned struct_cbq_interface_sz = sizeof(cbq_interface);
572unsigned struct_cbq_modify_class_sz = sizeof(cbq_modify_class);
573unsigned struct_ccd_ioctl_sz = sizeof(ccd_ioctl);
574unsigned struct_cdnr_add_element_sz = sizeof(cdnr_add_element);
575unsigned struct_cdnr_add_filter_sz = sizeof(cdnr_add_filter);
576unsigned struct_cdnr_add_tbmeter_sz = sizeof(cdnr_add_tbmeter);
577unsigned struct_cdnr_add_trtcm_sz = sizeof(cdnr_add_trtcm);
578unsigned struct_cdnr_add_tswtcm_sz = sizeof(cdnr_add_tswtcm);
579unsigned struct_cdnr_delete_element_sz = sizeof(cdnr_delete_element);
580unsigned struct_cdnr_delete_filter_sz = sizeof(cdnr_delete_filter);
581unsigned struct_cdnr_get_stats_sz = sizeof(cdnr_get_stats);
582unsigned struct_cdnr_interface_sz = sizeof(cdnr_interface);
583unsigned struct_cdnr_modify_tbmeter_sz = sizeof(cdnr_modify_tbmeter);
584unsigned struct_cdnr_modify_trtcm_sz = sizeof(cdnr_modify_trtcm);
585unsigned struct_cdnr_modify_tswtcm_sz = sizeof(cdnr_modify_tswtcm);
586unsigned struct_cdnr_tbmeter_stats_sz = sizeof(cdnr_tbmeter_stats);
587unsigned struct_cdnr_tcm_stats_sz = sizeof(cdnr_tcm_stats);
588unsigned struct_cgd_ioctl_sz = sizeof(cgd_ioctl);
589unsigned struct_cgd_user_sz = sizeof(cgd_user);
590unsigned struct_changer_element_status_request_sz =
591 sizeof(changer_element_status_request);
592unsigned struct_changer_exchange_request_sz = sizeof(changer_exchange_request);
593unsigned struct_changer_move_request_sz = sizeof(changer_move_request);
594unsigned struct_changer_params_sz = sizeof(changer_params);
595unsigned struct_changer_position_request_sz = sizeof(changer_position_request);
596unsigned struct_changer_set_voltag_request_sz =
597 sizeof(changer_set_voltag_request);
598unsigned struct_clockctl_adjtime_sz = sizeof(clockctl_adjtime);
599unsigned struct_clockctl_clock_settime_sz = sizeof(clockctl_clock_settime);
600unsigned struct_clockctl_ntp_adjtime_sz = sizeof(clockctl_ntp_adjtime);
601unsigned struct_clockctl_settimeofday_sz = sizeof(clockctl_settimeofday);
602unsigned struct_cnwistats_sz = sizeof(cnwistats);
603unsigned struct_cnwitrail_sz = sizeof(cnwitrail);
604unsigned struct_cnwstatus_sz = sizeof(cnwstatus);
605unsigned struct_count_info_sz = sizeof(count_info);
606unsigned struct_cpu_ucode_sz = sizeof(cpu_ucode);
607unsigned struct_cpu_ucode_version_sz = sizeof(cpu_ucode_version);
608unsigned struct_crypt_kop_sz = sizeof(crypt_kop);
609unsigned struct_crypt_mkop_sz = sizeof(crypt_mkop);
610unsigned struct_crypt_mop_sz = sizeof(crypt_mop);
611unsigned struct_crypt_op_sz = sizeof(crypt_op);
612unsigned struct_crypt_result_sz = sizeof(crypt_result);
613unsigned struct_crypt_sfop_sz = sizeof(crypt_sfop);
614unsigned struct_crypt_sgop_sz = sizeof(crypt_sgop);
615unsigned struct_cryptret_sz = sizeof(cryptret);
616unsigned struct_devdetachargs_sz = sizeof(devdetachargs);
617unsigned struct_devlistargs_sz = sizeof(devlistargs);
618unsigned struct_devpmargs_sz = sizeof(devpmargs);
619unsigned struct_devrescanargs_sz = sizeof(devrescanargs);
620unsigned struct_disk_badsecinfo_sz = sizeof(disk_badsecinfo);
621unsigned struct_disk_strategy_sz = sizeof(disk_strategy);
622unsigned struct_disklabel_sz = sizeof(disklabel);
623unsigned struct_dkbad_sz = sizeof(dkbad);
624unsigned struct_dkwedge_info_sz = sizeof(dkwedge_info);
625unsigned struct_dkwedge_list_sz = sizeof(dkwedge_list);
626unsigned struct_dmio_setfunc_sz = sizeof(dmio_setfunc);
627unsigned struct_dmx_pes_filter_params_sz = sizeof(dmx_pes_filter_params);
628unsigned struct_dmx_sct_filter_params_sz = sizeof(dmx_sct_filter_params);
629unsigned struct_dmx_stc_sz = sizeof(dmx_stc);
630unsigned struct_dvb_diseqc_master_cmd_sz = sizeof(dvb_diseqc_master_cmd);
631unsigned struct_dvb_diseqc_slave_reply_sz = sizeof(dvb_diseqc_slave_reply);
632unsigned struct_dvb_frontend_event_sz = sizeof(dvb_frontend_event);
633unsigned struct_dvb_frontend_info_sz = sizeof(dvb_frontend_info);
634unsigned struct_dvb_frontend_parameters_sz = sizeof(dvb_frontend_parameters);
635unsigned struct_eccapreq_sz = sizeof(eccapreq);
636unsigned struct_fbcmap_sz = sizeof(fbcmap);
637unsigned struct_fbcurpos_sz = sizeof(fbcurpos);
638unsigned struct_fbcursor_sz = sizeof(fbcursor);
639unsigned struct_fbgattr_sz = sizeof(fbgattr);
640unsigned struct_fbsattr_sz = sizeof(fbsattr);
641unsigned struct_fbtype_sz = sizeof(fbtype);
642unsigned struct_fdformat_cmd_sz = sizeof(fdformat_cmd);
643unsigned struct_fdformat_parms_sz = sizeof(fdformat_parms);
644unsigned struct_fifoq_conf_sz = sizeof(fifoq_conf);
645unsigned struct_fifoq_getstats_sz = sizeof(fifoq_getstats);
646unsigned struct_fifoq_interface_sz = sizeof(fifoq_interface);
647unsigned struct_format_op_sz = sizeof(format_op);
648unsigned struct_fss_get_sz = sizeof(fss_get);
649unsigned struct_fss_set_sz = sizeof(fss_set);
650unsigned struct_gpio_attach_sz = sizeof(gpio_attach);
651unsigned struct_gpio_info_sz = sizeof(gpio_info);
652unsigned struct_gpio_req_sz = sizeof(gpio_req);
653unsigned struct_gpio_set_sz = sizeof(gpio_set);
654unsigned struct_hfsc_add_class_sz = sizeof(hfsc_add_class);
655unsigned struct_hfsc_add_filter_sz = sizeof(hfsc_add_filter);
656unsigned struct_hfsc_attach_sz = sizeof(hfsc_attach);
657unsigned struct_hfsc_class_stats_sz = sizeof(hfsc_class_stats);
658unsigned struct_hfsc_delete_class_sz = sizeof(hfsc_delete_class);
659unsigned struct_hfsc_delete_filter_sz = sizeof(hfsc_delete_filter);
660unsigned struct_hfsc_interface_sz = sizeof(hfsc_interface);
661unsigned struct_hfsc_modify_class_sz = sizeof(hfsc_modify_class);
662unsigned struct_hpcfb_dsp_op_sz = sizeof(hpcfb_dsp_op);
663unsigned struct_hpcfb_dspconf_sz = sizeof(hpcfb_dspconf);
664unsigned struct_hpcfb_fbconf_sz = sizeof(hpcfb_fbconf);
665unsigned struct_if_addrprefreq_sz = sizeof(if_addrprefreq);
666unsigned struct_if_clonereq_sz = sizeof(if_clonereq);
667unsigned struct_if_laddrreq_sz = sizeof(if_laddrreq);
668unsigned struct_ifaddr_sz = sizeof(ifaddr);
669unsigned struct_ifaliasreq_sz = sizeof(ifaliasreq);
670unsigned struct_ifcapreq_sz = sizeof(ifcapreq);
671unsigned struct_ifconf_sz = sizeof(ifconf);
672unsigned struct_ifdatareq_sz = sizeof(ifdatareq);
673unsigned struct_ifdrv_sz = sizeof(ifdrv);
674unsigned struct_ifmediareq_sz = sizeof(ifmediareq);
675unsigned struct_ifpppcstatsreq_sz = sizeof(ifpppcstatsreq);
676unsigned struct_ifpppstatsreq_sz = sizeof(ifpppstatsreq);
677unsigned struct_ifreq_sz = sizeof(ifreq);
678unsigned struct_in6_addrpolicy_sz = sizeof(in6_addrpolicy);
679unsigned struct_in6_ndireq_sz = sizeof(in6_ndireq);
680unsigned struct_ioc_load_unload_sz = sizeof(ioc_load_unload);
681unsigned struct_ioc_patch_sz = sizeof(ioc_patch);
682unsigned struct_ioc_play_blocks_sz = sizeof(ioc_play_blocks);
683unsigned struct_ioc_play_msf_sz = sizeof(ioc_play_msf);
684unsigned struct_ioc_play_track_sz = sizeof(ioc_play_track);
685unsigned struct_ioc_read_subchannel_sz = sizeof(ioc_read_subchannel);
686unsigned struct_ioc_read_toc_entry_sz = sizeof(ioc_read_toc_entry);
687unsigned struct_ioc_toc_header_sz = sizeof(ioc_toc_header);
688unsigned struct_ioc_vol_sz = sizeof(ioc_vol);
689unsigned struct_ioctl_pt_sz = sizeof(ioctl_pt);
690unsigned struct_ioppt_sz = sizeof(ioppt);
691unsigned struct_iovec_sz = sizeof(iovec);
692unsigned struct_ipfobj_sz = sizeof(ipfobj);
693unsigned struct_irda_params_sz = sizeof(irda_params);
694unsigned struct_isp_fc_device_sz = sizeof(isp_fc_device);
695unsigned struct_isp_fc_tsk_mgmt_sz = sizeof(isp_fc_tsk_mgmt);
696unsigned struct_isp_hba_device_sz = sizeof(isp_hba_device);
697unsigned struct_isv_cmd_sz = sizeof(isv_cmd);
698unsigned struct_jobs_add_class_sz = sizeof(jobs_add_class);
699unsigned struct_jobs_add_filter_sz = sizeof(jobs_add_filter);
700unsigned struct_jobs_attach_sz = sizeof(jobs_attach);
701unsigned struct_jobs_class_stats_sz = sizeof(jobs_class_stats);
702unsigned struct_jobs_delete_class_sz = sizeof(jobs_delete_class);
703unsigned struct_jobs_delete_filter_sz = sizeof(jobs_delete_filter);
704unsigned struct_jobs_interface_sz = sizeof(jobs_interface);
705unsigned struct_jobs_modify_class_sz = sizeof(jobs_modify_class);
706unsigned struct_kbentry_sz = sizeof(kbentry);
707unsigned struct_kfilter_mapping_sz = sizeof(kfilter_mapping);
708unsigned struct_kiockeymap_sz = sizeof(kiockeymap);
709unsigned struct_ksyms_gsymbol_sz = sizeof(ksyms_gsymbol);
710unsigned struct_ksyms_gvalue_sz = sizeof(ksyms_gvalue);
711unsigned struct_ksyms_ogsymbol_sz = sizeof(ksyms_ogsymbol);
712unsigned struct_kttcp_io_args_sz = sizeof(kttcp_io_args);
713unsigned struct_ltchars_sz = sizeof(ltchars);
714unsigned struct_lua_create_sz = sizeof(struct lua_create);
715unsigned struct_lua_info_sz = sizeof(struct lua_info);
716unsigned struct_lua_load_sz = sizeof(struct lua_load);
717unsigned struct_lua_require_sz = sizeof(lua_require);
718unsigned struct_mbpp_param_sz = sizeof(mbpp_param);
719unsigned struct_md_conf_sz = sizeof(md_conf);
720unsigned struct_meteor_capframe_sz = sizeof(meteor_capframe);
721unsigned struct_meteor_counts_sz = sizeof(meteor_counts);
722unsigned struct_meteor_geomet_sz = sizeof(meteor_geomet);
723unsigned struct_meteor_pixfmt_sz = sizeof(meteor_pixfmt);
724unsigned struct_meteor_video_sz = sizeof(meteor_video);
725unsigned struct_mlx_cinfo_sz = sizeof(mlx_cinfo);
726unsigned struct_mlx_pause_sz = sizeof(mlx_pause);
727unsigned struct_mlx_rebuild_request_sz = sizeof(mlx_rebuild_request);
728unsigned struct_mlx_rebuild_status_sz = sizeof(mlx_rebuild_status);
729unsigned struct_mlx_usercommand_sz = sizeof(mlx_usercommand);
730unsigned struct_mly_user_command_sz = sizeof(mly_user_command);
731unsigned struct_mly_user_health_sz = sizeof(mly_user_health);
732unsigned struct_mtget_sz = sizeof(mtget);
733unsigned struct_mtop_sz = sizeof(mtop);
734unsigned struct_npf_ioctl_table_sz = sizeof(npf_ioctl_table);
735unsigned struct_npioctl_sz = sizeof(npioctl);
736unsigned struct_nvme_pt_command_sz = sizeof(nvme_pt_command);
737unsigned struct_ochanger_element_status_request_sz =
738 sizeof(ochanger_element_status_request);
739unsigned struct_ofiocdesc_sz = sizeof(ofiocdesc);
740unsigned struct_okiockey_sz = sizeof(okiockey);
741unsigned struct_ortentry_sz = sizeof(ortentry);
742unsigned struct_oscsi_addr_sz = sizeof(oscsi_addr);
743unsigned struct_oss_audioinfo_sz = sizeof(oss_audioinfo);
744unsigned struct_oss_sysinfo_sz = sizeof(oss_sysinfo);
745unsigned struct_pciio_bdf_cfgreg_sz = sizeof(pciio_bdf_cfgreg);
746unsigned struct_pciio_businfo_sz = sizeof(pciio_businfo);
747unsigned struct_pciio_cfgreg_sz = sizeof(pciio_cfgreg);
748unsigned struct_pciio_drvname_sz = sizeof(pciio_drvname);
749unsigned struct_pciio_drvnameonbus_sz = sizeof(pciio_drvnameonbus);
750unsigned struct_pcvtid_sz = sizeof(pcvtid);
751unsigned struct_pf_osfp_ioctl_sz = sizeof(pf_osfp_ioctl);
752unsigned struct_pf_status_sz = sizeof(pf_status);
753unsigned struct_pfioc_altq_sz = sizeof(pfioc_altq);
754unsigned struct_pfioc_if_sz = sizeof(pfioc_if);
755unsigned struct_pfioc_iface_sz = sizeof(pfioc_iface);
756unsigned struct_pfioc_limit_sz = sizeof(pfioc_limit);
757unsigned struct_pfioc_natlook_sz = sizeof(pfioc_natlook);
758unsigned struct_pfioc_pooladdr_sz = sizeof(pfioc_pooladdr);
759unsigned struct_pfioc_qstats_sz = sizeof(pfioc_qstats);
760unsigned struct_pfioc_rule_sz = sizeof(pfioc_rule);
761unsigned struct_pfioc_ruleset_sz = sizeof(pfioc_ruleset);
762unsigned struct_pfioc_src_node_kill_sz = sizeof(pfioc_src_node_kill);
763unsigned struct_pfioc_src_nodes_sz = sizeof(pfioc_src_nodes);
764unsigned struct_pfioc_state_kill_sz = sizeof(pfioc_state_kill);
765unsigned struct_pfioc_state_sz = sizeof(pfioc_state);
766unsigned struct_pfioc_states_sz = sizeof(pfioc_states);
767unsigned struct_pfioc_table_sz = sizeof(pfioc_table);
768unsigned struct_pfioc_tm_sz = sizeof(pfioc_tm);
769unsigned struct_pfioc_trans_sz = sizeof(pfioc_trans);
770unsigned struct_plistref_sz = sizeof(plistref);
771unsigned struct_power_type_sz = sizeof(power_type);
772unsigned struct_ppp_idle_sz = sizeof(ppp_idle);
773unsigned struct_ppp_option_data_sz = sizeof(ppp_option_data);
774unsigned struct_ppp_rawin_sz = sizeof(ppp_rawin);
775unsigned struct_pppoeconnectionstate_sz = sizeof(pppoeconnectionstate);
776unsigned struct_pppoediscparms_sz = sizeof(pppoediscparms);
777unsigned struct_priq_add_class_sz = sizeof(priq_add_class);
778unsigned struct_priq_add_filter_sz = sizeof(priq_add_filter);
779unsigned struct_priq_class_stats_sz = sizeof(priq_class_stats);
780unsigned struct_priq_delete_class_sz = sizeof(priq_delete_class);
781unsigned struct_priq_delete_filter_sz = sizeof(priq_delete_filter);
782unsigned struct_priq_interface_sz = sizeof(priq_interface);
783unsigned struct_priq_modify_class_sz = sizeof(priq_modify_class);
784unsigned struct_ptmget_sz = sizeof(ptmget);
785unsigned struct_radio_info_sz = sizeof(radio_info);
786unsigned struct_red_conf_sz = sizeof(red_conf);
787unsigned struct_red_interface_sz = sizeof(red_interface);
788unsigned struct_red_stats_sz = sizeof(red_stats);
789unsigned struct_redparams_sz = sizeof(redparams);
790unsigned struct_rf_pmparams_sz = sizeof(rf_pmparams);
791unsigned struct_rf_pmstat_sz = sizeof(rf_pmstat);
792unsigned struct_rf_recon_req_sz = sizeof(rf_recon_req);
793unsigned struct_rio_conf_sz = sizeof(rio_conf);
794unsigned struct_rio_interface_sz = sizeof(rio_interface);
795unsigned struct_rio_stats_sz = sizeof(rio_stats);
796unsigned struct_scan_io_sz = sizeof(scan_io);
797unsigned struct_scbusaccel_args_sz = sizeof(scbusaccel_args);
798unsigned struct_scbusiodetach_args_sz = sizeof(scbusiodetach_args);
799unsigned struct_scbusioscan_args_sz = sizeof(scbusioscan_args);
800unsigned struct_scsi_addr_sz = sizeof(scsi_addr);
801unsigned struct_seq_event_rec_sz = sizeof(seq_event_rec);
802unsigned struct_session_op_sz = sizeof(session_op);
803unsigned struct_sgttyb_sz = sizeof(sgttyb);
804unsigned struct_sioc_sg_req_sz = sizeof(sioc_sg_req);
805unsigned struct_sioc_vif_req_sz = sizeof(sioc_vif_req);
806unsigned struct_smbioc_flags_sz = sizeof(smbioc_flags);
807unsigned struct_smbioc_lookup_sz = sizeof(smbioc_lookup);
808unsigned struct_smbioc_oshare_sz = sizeof(smbioc_oshare);
809unsigned struct_smbioc_ossn_sz = sizeof(smbioc_ossn);
810unsigned struct_smbioc_rq_sz = sizeof(smbioc_rq);
811unsigned struct_smbioc_rw_sz = sizeof(smbioc_rw);
812unsigned struct_spppauthcfg_sz = sizeof(spppauthcfg);
813unsigned struct_spppauthfailuresettings_sz = sizeof(spppauthfailuresettings);
814unsigned struct_spppauthfailurestats_sz = sizeof(spppauthfailurestats);
815unsigned struct_spppdnsaddrs_sz = sizeof(spppdnsaddrs);
816unsigned struct_spppdnssettings_sz = sizeof(spppdnssettings);
817unsigned struct_spppidletimeout_sz = sizeof(spppidletimeout);
818unsigned struct_spppkeepalivesettings_sz = sizeof(spppkeepalivesettings);
819unsigned struct_sppplcpcfg_sz = sizeof(sppplcpcfg);
820unsigned struct_spppstatus_sz = sizeof(spppstatus);
821unsigned struct_spppstatusncp_sz = sizeof(spppstatusncp);
822unsigned struct_srt_rt_sz = sizeof(srt_rt);
823unsigned struct_stic_xinfo_sz = sizeof(stic_xinfo);
824unsigned struct_sun_dkctlr_sz = sizeof(sun_dkctlr);
825unsigned struct_sun_dkgeom_sz = sizeof(sun_dkgeom);
826unsigned struct_sun_dkpart_sz = sizeof(sun_dkpart);
827unsigned struct_synth_info_sz = sizeof(synth_info);
828unsigned struct_tbrreq_sz = sizeof(tbrreq);
829unsigned struct_tchars_sz = sizeof(tchars);
830unsigned struct_termios_sz = sizeof(termios);
831unsigned struct_timeval_sz = sizeof(timeval);
832unsigned struct_twe_drivecommand_sz = sizeof(twe_drivecommand);
833unsigned struct_twe_paramcommand_sz = sizeof(twe_paramcommand);
834unsigned struct_twe_usercommand_sz = sizeof(twe_usercommand);
835unsigned struct_ukyopon_identify_sz = sizeof(ukyopon_identify);
836unsigned struct_urio_command_sz = sizeof(urio_command);
837unsigned struct_usb_alt_interface_sz = sizeof(usb_alt_interface);
838unsigned struct_usb_bulk_ra_wb_opt_sz = sizeof(usb_bulk_ra_wb_opt);
839unsigned struct_usb_config_desc_sz = sizeof(usb_config_desc);
840unsigned struct_usb_ctl_report_desc_sz = sizeof(usb_ctl_report_desc);
841unsigned struct_usb_ctl_report_sz = sizeof(usb_ctl_report);
842unsigned struct_usb_ctl_request_sz = sizeof(usb_ctl_request);
843#if defined(__x86_64__)
844unsigned struct_nvmm_ioc_capability_sz = sizeof(nvmm_ioc_capability);
845unsigned struct_nvmm_ioc_machine_create_sz = sizeof(nvmm_ioc_machine_create);
846unsigned struct_nvmm_ioc_machine_destroy_sz = sizeof(nvmm_ioc_machine_destroy);
847unsigned struct_nvmm_ioc_machine_configure_sz =
848 sizeof(nvmm_ioc_machine_configure);
849unsigned struct_nvmm_ioc_vcpu_create_sz = sizeof(nvmm_ioc_vcpu_create);
850unsigned struct_nvmm_ioc_vcpu_destroy_sz = sizeof(nvmm_ioc_vcpu_destroy);
851unsigned struct_nvmm_ioc_vcpu_configure_sz = sizeof(nvmm_ioc_vcpu_configure);
852unsigned struct_nvmm_ioc_vcpu_setstate_sz = sizeof(nvmm_ioc_vcpu_destroy);
853unsigned struct_nvmm_ioc_vcpu_getstate_sz = sizeof(nvmm_ioc_vcpu_getstate);
854unsigned struct_nvmm_ioc_vcpu_inject_sz = sizeof(nvmm_ioc_vcpu_inject);
855unsigned struct_nvmm_ioc_vcpu_run_sz = sizeof(nvmm_ioc_vcpu_run);
856unsigned struct_nvmm_ioc_gpa_map_sz = sizeof(nvmm_ioc_gpa_map);
857unsigned struct_nvmm_ioc_gpa_unmap_sz = sizeof(nvmm_ioc_gpa_unmap);
858unsigned struct_nvmm_ioc_hva_map_sz = sizeof(nvmm_ioc_hva_map);
859unsigned struct_nvmm_ioc_hva_unmap_sz = sizeof(nvmm_ioc_hva_unmap);
860unsigned struct_nvmm_ioc_ctl_sz = sizeof(nvmm_ioc_ctl);
861#endif
862unsigned struct_spi_ioctl_configure_sz = sizeof(spi_ioctl_configure);
863unsigned struct_spi_ioctl_transfer_sz = sizeof(spi_ioctl_transfer);
864unsigned struct_autofs_daemon_request_sz = sizeof(autofs_daemon_request);
865unsigned struct_autofs_daemon_done_sz = sizeof(autofs_daemon_done);
866unsigned struct_sctp_connectx_addrs_sz = sizeof(sctp_connectx_addrs);
867unsigned struct_usb_device_info_old_sz = sizeof(usb_device_info_old);
868unsigned struct_usb_device_info_sz = sizeof(usb_device_info);
869unsigned struct_usb_device_stats_sz = sizeof(usb_device_stats);
870unsigned struct_usb_endpoint_desc_sz = sizeof(usb_endpoint_desc);
871unsigned struct_usb_full_desc_sz = sizeof(usb_full_desc);
872unsigned struct_usb_interface_desc_sz = sizeof(usb_interface_desc);
873unsigned struct_usb_string_desc_sz = sizeof(usb_string_desc);
874unsigned struct_utoppy_readfile_sz = sizeof(utoppy_readfile);
875unsigned struct_utoppy_rename_sz = sizeof(utoppy_rename);
876unsigned struct_utoppy_stats_sz = sizeof(utoppy_stats);
877unsigned struct_utoppy_writefile_sz = sizeof(utoppy_writefile);
878unsigned struct_v4l2_audio_sz = sizeof(v4l2_audio);
879unsigned struct_v4l2_audioout_sz = sizeof(v4l2_audioout);
880unsigned struct_v4l2_buffer_sz = sizeof(v4l2_buffer);
881unsigned struct_v4l2_capability_sz = sizeof(v4l2_capability);
882unsigned struct_v4l2_control_sz = sizeof(v4l2_control);
883unsigned struct_v4l2_crop_sz = sizeof(v4l2_crop);
884unsigned struct_v4l2_cropcap_sz = sizeof(v4l2_cropcap);
885unsigned struct_v4l2_fmtdesc_sz = sizeof(v4l2_fmtdesc);
886unsigned struct_v4l2_format_sz = sizeof(v4l2_format);
887unsigned struct_v4l2_framebuffer_sz = sizeof(v4l2_framebuffer);
888unsigned struct_v4l2_frequency_sz = sizeof(v4l2_frequency);
889unsigned struct_v4l2_frmivalenum_sz = sizeof(v4l2_frmivalenum);
890unsigned struct_v4l2_frmsizeenum_sz = sizeof(v4l2_frmsizeenum);
891unsigned struct_v4l2_input_sz = sizeof(v4l2_input);
892unsigned struct_v4l2_jpegcompression_sz = sizeof(v4l2_jpegcompression);
893unsigned struct_v4l2_modulator_sz = sizeof(v4l2_modulator);
894unsigned struct_v4l2_output_sz = sizeof(v4l2_output);
895unsigned struct_v4l2_queryctrl_sz = sizeof(v4l2_queryctrl);
896unsigned struct_v4l2_querymenu_sz = sizeof(v4l2_querymenu);
897unsigned struct_v4l2_requestbuffers_sz = sizeof(v4l2_requestbuffers);
898unsigned struct_v4l2_standard_sz = sizeof(v4l2_standard);
899unsigned struct_v4l2_streamparm_sz = sizeof(v4l2_streamparm);
900unsigned struct_v4l2_tuner_sz = sizeof(v4l2_tuner);
901unsigned struct_vnd_ioctl_sz = sizeof(vnd_ioctl);
902unsigned struct_vnd_user_sz = sizeof(vnd_user);
903unsigned struct_vt_stat_sz = sizeof(vt_stat);
904unsigned struct_wdog_conf_sz = sizeof(wdog_conf);
905unsigned struct_wdog_mode_sz = sizeof(wdog_mode);
906unsigned struct_ipmi_recv_sz = sizeof(ipmi_recv);
907unsigned struct_ipmi_req_sz = sizeof(ipmi_req);
908unsigned struct_ipmi_cmdspec_sz = sizeof(ipmi_cmdspec);
909unsigned struct_wfq_conf_sz = sizeof(wfq_conf);
910unsigned struct_wfq_getqid_sz = sizeof(wfq_getqid);
911unsigned struct_wfq_getstats_sz = sizeof(wfq_getstats);
912unsigned struct_wfq_interface_sz = sizeof(wfq_interface);
913unsigned struct_wfq_setweight_sz = sizeof(wfq_setweight);
914unsigned struct_winsize_sz = sizeof(winsize);
915unsigned struct_wscons_event_sz = sizeof(wscons_event);
916unsigned struct_wsdisplay_addscreendata_sz = sizeof(wsdisplay_addscreendata);
917unsigned struct_wsdisplay_char_sz = sizeof(wsdisplay_char);
918unsigned struct_wsdisplay_cmap_sz = sizeof(wsdisplay_cmap);
919unsigned struct_wsdisplay_curpos_sz = sizeof(wsdisplay_curpos);
920unsigned struct_wsdisplay_cursor_sz = sizeof(wsdisplay_cursor);
921unsigned struct_wsdisplay_delscreendata_sz = sizeof(wsdisplay_delscreendata);
922unsigned struct_wsdisplay_fbinfo_sz = sizeof(wsdisplay_fbinfo);
923unsigned struct_wsdisplay_font_sz = sizeof(wsdisplay_font);
924unsigned struct_wsdisplay_kbddata_sz = sizeof(wsdisplay_kbddata);
925unsigned struct_wsdisplay_msgattrs_sz = sizeof(wsdisplay_msgattrs);
926unsigned struct_wsdisplay_param_sz = sizeof(wsdisplay_param);
927unsigned struct_wsdisplay_scroll_data_sz = sizeof(wsdisplay_scroll_data);
928unsigned struct_wsdisplay_usefontdata_sz = sizeof(wsdisplay_usefontdata);
929unsigned struct_wsdisplayio_blit_sz = sizeof(wsdisplayio_blit);
930unsigned struct_wsdisplayio_bus_id_sz = sizeof(wsdisplayio_bus_id);
931unsigned struct_wsdisplayio_edid_info_sz = sizeof(wsdisplayio_edid_info);
932unsigned struct_wsdisplayio_fbinfo_sz = sizeof(wsdisplayio_fbinfo);
933unsigned struct_wskbd_bell_data_sz = sizeof(wskbd_bell_data);
934unsigned struct_wskbd_keyrepeat_data_sz = sizeof(wskbd_keyrepeat_data);
935unsigned struct_wskbd_map_data_sz = sizeof(wskbd_map_data);
936unsigned struct_wskbd_scroll_data_sz = sizeof(wskbd_scroll_data);
937unsigned struct_wsmouse_calibcoords_sz = sizeof(wsmouse_calibcoords);
938unsigned struct_wsmouse_id_sz = sizeof(wsmouse_id);
939unsigned struct_wsmouse_repeat_sz = sizeof(wsmouse_repeat);
940unsigned struct_wsmux_device_list_sz = sizeof(wsmux_device_list);
941unsigned struct_wsmux_device_sz = sizeof(wsmux_device);
942unsigned struct_xd_iocmd_sz = sizeof(xd_iocmd);
943
944unsigned struct_scsireq_sz = sizeof(struct scsireq);
945unsigned struct_tone_sz = sizeof(tone_t);
946unsigned union_twe_statrequest_sz = sizeof(union twe_statrequest);
947unsigned struct_usb_device_descriptor_sz = sizeof(usb_device_descriptor_t);
948unsigned struct_vt_mode_sz = sizeof(struct vt_mode);
949unsigned struct__old_mixer_info_sz = sizeof(struct _old_mixer_info);
950unsigned struct__agp_allocate_sz = sizeof(struct _agp_allocate);
951unsigned struct__agp_bind_sz = sizeof(struct _agp_bind);
952unsigned struct__agp_info_sz = sizeof(struct _agp_info);
953unsigned struct__agp_setup_sz = sizeof(struct _agp_setup);
954unsigned struct__agp_unbind_sz = sizeof(struct _agp_unbind);
955unsigned struct_atareq_sz = sizeof(struct atareq);
956unsigned struct_cpustate_sz = sizeof(struct cpustate);
957unsigned struct_dmx_caps_sz = sizeof(struct dmx_caps);
958unsigned enum_dmx_source_sz = sizeof(dmx_source_t);
959unsigned union_dvd_authinfo_sz = sizeof(dvd_authinfo);
960unsigned union_dvd_struct_sz = sizeof(dvd_struct);
961unsigned enum_v4l2_priority_sz = sizeof(enum v4l2_priority);
962unsigned struct_envsys_basic_info_sz = sizeof(struct envsys_basic_info);
963unsigned struct_envsys_tre_data_sz = sizeof(struct envsys_tre_data);
964unsigned enum_fe_sec_mini_cmd_sz = sizeof(enum fe_sec_mini_cmd);
965unsigned enum_fe_sec_tone_mode_sz = sizeof(enum fe_sec_tone_mode);
966unsigned enum_fe_sec_voltage_sz = sizeof(enum fe_sec_voltage);
967unsigned enum_fe_status_sz = sizeof(enum fe_status);
968unsigned struct_gdt_ctrt_sz = sizeof(struct gdt_ctrt);
969unsigned struct_gdt_event_sz = sizeof(struct gdt_event);
970unsigned struct_gdt_osv_sz = sizeof(struct gdt_osv);
971unsigned struct_gdt_rescan_sz = sizeof(struct gdt_rescan);
972unsigned struct_gdt_statist_sz = sizeof(struct gdt_statist);
973unsigned struct_gdt_ucmd_sz = sizeof(struct gdt_ucmd);
974unsigned struct_iscsi_conn_status_parameters_sz =
975 sizeof(iscsi_conn_status_parameters_t);
976unsigned struct_iscsi_get_version_parameters_sz =
977 sizeof(iscsi_get_version_parameters_t);
978unsigned struct_iscsi_iocommand_parameters_sz =
979 sizeof(iscsi_iocommand_parameters_t);
980unsigned struct_iscsi_login_parameters_sz = sizeof(iscsi_login_parameters_t);
981unsigned struct_iscsi_logout_parameters_sz = sizeof(iscsi_logout_parameters_t);
982unsigned struct_iscsi_register_event_parameters_sz =
983 sizeof(iscsi_register_event_parameters_t);
984unsigned struct_iscsi_remove_parameters_sz = sizeof(iscsi_remove_parameters_t);
985unsigned struct_iscsi_send_targets_parameters_sz =
986 sizeof(iscsi_send_targets_parameters_t);
987unsigned struct_iscsi_set_node_name_parameters_sz =
988 sizeof(iscsi_set_node_name_parameters_t);
989unsigned struct_iscsi_wait_event_parameters_sz =
990 sizeof(iscsi_wait_event_parameters_t);
991unsigned struct_isp_stats_sz = sizeof(isp_stats_t);
992unsigned struct_lsenable_sz = sizeof(struct lsenable);
993unsigned struct_lsdisable_sz = sizeof(struct lsdisable);
994unsigned struct_audio_format_query_sz = sizeof(audio_format_query);
995unsigned struct_mixer_ctrl_sz = sizeof(struct mixer_ctrl);
996unsigned struct_mixer_devinfo_sz = sizeof(struct mixer_devinfo);
997unsigned struct_mpu_command_rec_sz = sizeof(mpu_command_rec);
998unsigned struct_rndstat_sz = sizeof(rndstat_t);
999unsigned struct_rndstat_name_sz = sizeof(rndstat_name_t);
1000unsigned struct_rndctl_sz = sizeof(rndctl_t);
1001unsigned struct_rnddata_sz = sizeof(rnddata_t);
1002unsigned struct_rndpoolstat_sz = sizeof(rndpoolstat_t);
1003unsigned struct_rndstat_est_sz = sizeof(rndstat_est_t);
1004unsigned struct_rndstat_est_name_sz = sizeof(rndstat_est_name_t);
1005unsigned struct_pps_params_sz = sizeof(pps_params_t);
1006unsigned struct_pps_info_sz = sizeof(pps_info_t);
1007unsigned struct_mixer_info_sz = sizeof(struct mixer_info);
1008unsigned struct_RF_SparetWait_sz = sizeof(RF_SparetWait_t);
1009unsigned struct_RF_ComponentLabel_sz = sizeof(RF_ComponentLabel_t);
1010unsigned struct_RF_SingleComponent_sz = sizeof(RF_SingleComponent_t);
1011unsigned struct_RF_ProgressInfo_sz = sizeof(RF_ProgressInfo_t);
1012unsigned struct_nvlist_ref_sz = sizeof(struct __sanitizer_nvlist_ref_t);
1013unsigned struct_StringList_sz = sizeof(StringList);
1014
1015const unsigned IOCTL_NOT_PRESENT = 0;
1016
1017unsigned IOCTL_AFM_ADDFMAP = AFM_ADDFMAP;
1018unsigned IOCTL_AFM_DELFMAP = AFM_DELFMAP;
1019unsigned IOCTL_AFM_CLEANFMAP = AFM_CLEANFMAP;
1020unsigned IOCTL_AFM_GETFMAP = AFM_GETFMAP;
1021unsigned IOCTL_ALTQGTYPE = ALTQGTYPE;
1022unsigned IOCTL_ALTQTBRSET = ALTQTBRSET;
1023unsigned IOCTL_ALTQTBRGET = ALTQTBRGET;
1024unsigned IOCTL_BLUE_IF_ATTACH = BLUE_IF_ATTACH;
1025unsigned IOCTL_BLUE_IF_DETACH = BLUE_IF_DETACH;
1026unsigned IOCTL_BLUE_ENABLE = BLUE_ENABLE;
1027unsigned IOCTL_BLUE_DISABLE = BLUE_DISABLE;
1028unsigned IOCTL_BLUE_CONFIG = BLUE_CONFIG;
1029unsigned IOCTL_BLUE_GETSTATS = BLUE_GETSTATS;
1030unsigned IOCTL_CBQ_IF_ATTACH = CBQ_IF_ATTACH;
1031unsigned IOCTL_CBQ_IF_DETACH = CBQ_IF_DETACH;
1032unsigned IOCTL_CBQ_ENABLE = CBQ_ENABLE;
1033unsigned IOCTL_CBQ_DISABLE = CBQ_DISABLE;
1034unsigned IOCTL_CBQ_CLEAR_HIERARCHY = CBQ_CLEAR_HIERARCHY;
1035unsigned IOCTL_CBQ_ADD_CLASS = CBQ_ADD_CLASS;
1036unsigned IOCTL_CBQ_DEL_CLASS = CBQ_DEL_CLASS;
1037unsigned IOCTL_CBQ_MODIFY_CLASS = CBQ_MODIFY_CLASS;
1038unsigned IOCTL_CBQ_ADD_FILTER = CBQ_ADD_FILTER;
1039unsigned IOCTL_CBQ_DEL_FILTER = CBQ_DEL_FILTER;
1040unsigned IOCTL_CBQ_GETSTATS = CBQ_GETSTATS;
1041unsigned IOCTL_CDNR_IF_ATTACH = CDNR_IF_ATTACH;
1042unsigned IOCTL_CDNR_IF_DETACH = CDNR_IF_DETACH;
1043unsigned IOCTL_CDNR_ENABLE = CDNR_ENABLE;
1044unsigned IOCTL_CDNR_DISABLE = CDNR_DISABLE;
1045unsigned IOCTL_CDNR_ADD_FILTER = CDNR_ADD_FILTER;
1046unsigned IOCTL_CDNR_DEL_FILTER = CDNR_DEL_FILTER;
1047unsigned IOCTL_CDNR_GETSTATS = CDNR_GETSTATS;
1048unsigned IOCTL_CDNR_ADD_ELEM = CDNR_ADD_ELEM;
1049unsigned IOCTL_CDNR_DEL_ELEM = CDNR_DEL_ELEM;
1050unsigned IOCTL_CDNR_ADD_TBM = CDNR_ADD_TBM;
1051unsigned IOCTL_CDNR_MOD_TBM = CDNR_MOD_TBM;
1052unsigned IOCTL_CDNR_TBM_STATS = CDNR_TBM_STATS;
1053unsigned IOCTL_CDNR_ADD_TCM = CDNR_ADD_TCM;
1054unsigned IOCTL_CDNR_MOD_TCM = CDNR_MOD_TCM;
1055unsigned IOCTL_CDNR_TCM_STATS = CDNR_TCM_STATS;
1056unsigned IOCTL_CDNR_ADD_TSW = CDNR_ADD_TSW;
1057unsigned IOCTL_CDNR_MOD_TSW = CDNR_MOD_TSW;
1058unsigned IOCTL_FIFOQ_IF_ATTACH = FIFOQ_IF_ATTACH;
1059unsigned IOCTL_FIFOQ_IF_DETACH = FIFOQ_IF_DETACH;
1060unsigned IOCTL_FIFOQ_ENABLE = FIFOQ_ENABLE;
1061unsigned IOCTL_FIFOQ_DISABLE = FIFOQ_DISABLE;
1062unsigned IOCTL_FIFOQ_CONFIG = FIFOQ_CONFIG;
1063unsigned IOCTL_FIFOQ_GETSTATS = FIFOQ_GETSTATS;
1064unsigned IOCTL_HFSC_IF_ATTACH = HFSC_IF_ATTACH;
1065unsigned IOCTL_HFSC_IF_DETACH = HFSC_IF_DETACH;
1066unsigned IOCTL_HFSC_ENABLE = HFSC_ENABLE;
1067unsigned IOCTL_HFSC_DISABLE = HFSC_DISABLE;
1068unsigned IOCTL_HFSC_CLEAR_HIERARCHY = HFSC_CLEAR_HIERARCHY;
1069unsigned IOCTL_HFSC_ADD_CLASS = HFSC_ADD_CLASS;
1070unsigned IOCTL_HFSC_DEL_CLASS = HFSC_DEL_CLASS;
1071unsigned IOCTL_HFSC_MOD_CLASS = HFSC_MOD_CLASS;
1072unsigned IOCTL_HFSC_ADD_FILTER = HFSC_ADD_FILTER;
1073unsigned IOCTL_HFSC_DEL_FILTER = HFSC_DEL_FILTER;
1074unsigned IOCTL_HFSC_GETSTATS = HFSC_GETSTATS;
1075unsigned IOCTL_JOBS_IF_ATTACH = JOBS_IF_ATTACH;
1076unsigned IOCTL_JOBS_IF_DETACH = JOBS_IF_DETACH;
1077unsigned IOCTL_JOBS_ENABLE = JOBS_ENABLE;
1078unsigned IOCTL_JOBS_DISABLE = JOBS_DISABLE;
1079unsigned IOCTL_JOBS_CLEAR = JOBS_CLEAR;
1080unsigned IOCTL_JOBS_ADD_CLASS = JOBS_ADD_CLASS;
1081unsigned IOCTL_JOBS_DEL_CLASS = JOBS_DEL_CLASS;
1082unsigned IOCTL_JOBS_MOD_CLASS = JOBS_MOD_CLASS;
1083unsigned IOCTL_JOBS_ADD_FILTER = JOBS_ADD_FILTER;
1084unsigned IOCTL_JOBS_DEL_FILTER = JOBS_DEL_FILTER;
1085unsigned IOCTL_JOBS_GETSTATS = JOBS_GETSTATS;
1086unsigned IOCTL_PRIQ_IF_ATTACH = PRIQ_IF_ATTACH;
1087unsigned IOCTL_PRIQ_IF_DETACH = PRIQ_IF_DETACH;
1088unsigned IOCTL_PRIQ_ENABLE = PRIQ_ENABLE;
1089unsigned IOCTL_PRIQ_DISABLE = PRIQ_DISABLE;
1090unsigned IOCTL_PRIQ_CLEAR = PRIQ_CLEAR;
1091unsigned IOCTL_PRIQ_ADD_CLASS = PRIQ_ADD_CLASS;
1092unsigned IOCTL_PRIQ_DEL_CLASS = PRIQ_DEL_CLASS;
1093unsigned IOCTL_PRIQ_MOD_CLASS = PRIQ_MOD_CLASS;
1094unsigned IOCTL_PRIQ_ADD_FILTER = PRIQ_ADD_FILTER;
1095unsigned IOCTL_PRIQ_DEL_FILTER = PRIQ_DEL_FILTER;
1096unsigned IOCTL_PRIQ_GETSTATS = PRIQ_GETSTATS;
1097unsigned IOCTL_RED_IF_ATTACH = RED_IF_ATTACH;
1098unsigned IOCTL_RED_IF_DETACH = RED_IF_DETACH;
1099unsigned IOCTL_RED_ENABLE = RED_ENABLE;
1100unsigned IOCTL_RED_DISABLE = RED_DISABLE;
1101unsigned IOCTL_RED_CONFIG = RED_CONFIG;
1102unsigned IOCTL_RED_GETSTATS = RED_GETSTATS;
1103unsigned IOCTL_RED_SETDEFAULTS = RED_SETDEFAULTS;
1104unsigned IOCTL_RIO_IF_ATTACH = RIO_IF_ATTACH;
1105unsigned IOCTL_RIO_IF_DETACH = RIO_IF_DETACH;
1106unsigned IOCTL_RIO_ENABLE = RIO_ENABLE;
1107unsigned IOCTL_RIO_DISABLE = RIO_DISABLE;
1108unsigned IOCTL_RIO_CONFIG = RIO_CONFIG;
1109unsigned IOCTL_RIO_GETSTATS = RIO_GETSTATS;
1110unsigned IOCTL_RIO_SETDEFAULTS = RIO_SETDEFAULTS;
1111unsigned IOCTL_WFQ_IF_ATTACH = WFQ_IF_ATTACH;
1112unsigned IOCTL_WFQ_IF_DETACH = WFQ_IF_DETACH;
1113unsigned IOCTL_WFQ_ENABLE = WFQ_ENABLE;
1114unsigned IOCTL_WFQ_DISABLE = WFQ_DISABLE;
1115unsigned IOCTL_WFQ_CONFIG = WFQ_CONFIG;
1116unsigned IOCTL_WFQ_GET_STATS = WFQ_GET_STATS;
1117unsigned IOCTL_WFQ_GET_QID = WFQ_GET_QID;
1118unsigned IOCTL_WFQ_SET_WEIGHT = WFQ_SET_WEIGHT;
1119unsigned IOCTL_CRIOGET = CRIOGET;
1120unsigned IOCTL_CIOCFSESSION = CIOCFSESSION;
1121unsigned IOCTL_CIOCKEY = CIOCKEY;
1122unsigned IOCTL_CIOCNFKEYM = CIOCNFKEYM;
1123unsigned IOCTL_CIOCNFSESSION = CIOCNFSESSION;
1124unsigned IOCTL_CIOCNCRYPTRETM = CIOCNCRYPTRETM;
1125unsigned IOCTL_CIOCNCRYPTRET = CIOCNCRYPTRET;
1126unsigned IOCTL_CIOCGSESSION = CIOCGSESSION;
1127unsigned IOCTL_CIOCNGSESSION = CIOCNGSESSION;
1128unsigned IOCTL_CIOCCRYPT = CIOCCRYPT;
1129unsigned IOCTL_CIOCNCRYPTM = CIOCNCRYPTM;
1130unsigned IOCTL_CIOCASYMFEAT = CIOCASYMFEAT;
1131unsigned IOCTL_APM_IOC_REJECT = APM_IOC_REJECT;
1132unsigned IOCTL_APM_IOC_STANDBY = APM_IOC_STANDBY;
1133unsigned IOCTL_APM_IOC_SUSPEND = APM_IOC_SUSPEND;
1134unsigned IOCTL_OAPM_IOC_GETPOWER = OAPM_IOC_GETPOWER;
1135unsigned IOCTL_APM_IOC_GETPOWER = APM_IOC_GETPOWER;
1136unsigned IOCTL_APM_IOC_NEXTEVENT = APM_IOC_NEXTEVENT;
1137unsigned IOCTL_APM_IOC_DEV_CTL = APM_IOC_DEV_CTL;
1138unsigned IOCTL_NETBSD_DM_IOCTL = NETBSD_DM_IOCTL;
1139unsigned IOCTL_DMIO_SETFUNC = DMIO_SETFUNC;
1140unsigned IOCTL_DMX_START = DMX_START;
1141unsigned IOCTL_DMX_STOP = DMX_STOP;
1142unsigned IOCTL_DMX_SET_FILTER = DMX_SET_FILTER;
1143unsigned IOCTL_DMX_SET_PES_FILTER = DMX_SET_PES_FILTER;
1144unsigned IOCTL_DMX_SET_BUFFER_SIZE = DMX_SET_BUFFER_SIZE;
1145unsigned IOCTL_DMX_GET_STC = DMX_GET_STC;
1146unsigned IOCTL_DMX_ADD_PID = DMX_ADD_PID;
1147unsigned IOCTL_DMX_REMOVE_PID = DMX_REMOVE_PID;
1148unsigned IOCTL_DMX_GET_CAPS = DMX_GET_CAPS;
1149unsigned IOCTL_DMX_SET_SOURCE = DMX_SET_SOURCE;
1150unsigned IOCTL_FE_READ_STATUS = FE_READ_STATUS;
1151unsigned IOCTL_FE_READ_BER = FE_READ_BER;
1152unsigned IOCTL_FE_READ_SNR = FE_READ_SNR;
1153unsigned IOCTL_FE_READ_SIGNAL_STRENGTH = FE_READ_SIGNAL_STRENGTH;
1154unsigned IOCTL_FE_READ_UNCORRECTED_BLOCKS = FE_READ_UNCORRECTED_BLOCKS;
1155unsigned IOCTL_FE_SET_FRONTEND = FE_SET_FRONTEND;
1156unsigned IOCTL_FE_GET_FRONTEND = FE_GET_FRONTEND;
1157unsigned IOCTL_FE_GET_EVENT = FE_GET_EVENT;
1158unsigned IOCTL_FE_GET_INFO = FE_GET_INFO;
1159unsigned IOCTL_FE_DISEQC_RESET_OVERLOAD = FE_DISEQC_RESET_OVERLOAD;
1160unsigned IOCTL_FE_DISEQC_SEND_MASTER_CMD = FE_DISEQC_SEND_MASTER_CMD;
1161unsigned IOCTL_FE_DISEQC_RECV_SLAVE_REPLY = FE_DISEQC_RECV_SLAVE_REPLY;
1162unsigned IOCTL_FE_DISEQC_SEND_BURST = FE_DISEQC_SEND_BURST;
1163unsigned IOCTL_FE_SET_TONE = FE_SET_TONE;
1164unsigned IOCTL_FE_SET_VOLTAGE = FE_SET_VOLTAGE;
1165unsigned IOCTL_FE_ENABLE_HIGH_LNB_VOLTAGE = FE_ENABLE_HIGH_LNB_VOLTAGE;
1166unsigned IOCTL_FE_SET_FRONTEND_TUNE_MODE = FE_SET_FRONTEND_TUNE_MODE;
1167unsigned IOCTL_FE_DISHNETWORK_SEND_LEGACY_CMD = FE_DISHNETWORK_SEND_LEGACY_CMD;
1168unsigned IOCTL_FILEMON_SET_FD = FILEMON_SET_FD;
1169unsigned IOCTL_FILEMON_SET_PID = FILEMON_SET_PID;
1170unsigned IOCTL_HDAUDIO_FGRP_INFO = HDAUDIO_FGRP_INFO;
1171unsigned IOCTL_HDAUDIO_FGRP_GETCONFIG = HDAUDIO_FGRP_GETCONFIG;
1172unsigned IOCTL_HDAUDIO_FGRP_SETCONFIG = HDAUDIO_FGRP_SETCONFIG;
1173unsigned IOCTL_HDAUDIO_FGRP_WIDGET_INFO = HDAUDIO_FGRP_WIDGET_INFO;
1174unsigned IOCTL_HDAUDIO_FGRP_CODEC_INFO = HDAUDIO_FGRP_CODEC_INFO;
1175unsigned IOCTL_HDAUDIO_AFG_WIDGET_INFO = HDAUDIO_AFG_WIDGET_INFO;
1176unsigned IOCTL_HDAUDIO_AFG_CODEC_INFO = HDAUDIO_AFG_CODEC_INFO;
1177unsigned IOCTL_CEC_GET_PHYS_ADDR = CEC_GET_PHYS_ADDR;
1178unsigned IOCTL_CEC_GET_LOG_ADDRS = CEC_GET_LOG_ADDRS;
1179unsigned IOCTL_CEC_SET_LOG_ADDRS = CEC_SET_LOG_ADDRS;
1180unsigned IOCTL_CEC_GET_VENDOR_ID = CEC_GET_VENDOR_ID;
1181unsigned IOCTL_HPCFBIO_GCONF = HPCFBIO_GCONF;
1182unsigned IOCTL_HPCFBIO_SCONF = HPCFBIO_SCONF;
1183unsigned IOCTL_HPCFBIO_GDSPCONF = HPCFBIO_GDSPCONF;
1184unsigned IOCTL_HPCFBIO_SDSPCONF = HPCFBIO_SDSPCONF;
1185unsigned IOCTL_HPCFBIO_GOP = HPCFBIO_GOP;
1186unsigned IOCTL_HPCFBIO_SOP = HPCFBIO_SOP;
1187unsigned IOCTL_IOPIOCPT = IOPIOCPT;
1188unsigned IOCTL_IOPIOCGLCT = IOPIOCGLCT;
1189unsigned IOCTL_IOPIOCGSTATUS = IOPIOCGSTATUS;
1190unsigned IOCTL_IOPIOCRECONFIG = IOPIOCRECONFIG;
1191unsigned IOCTL_IOPIOCGTIDMAP = IOPIOCGTIDMAP;
1192unsigned IOCTL_SIOCGATHSTATS = SIOCGATHSTATS;
1193unsigned IOCTL_SIOCGATHDIAG = SIOCGATHDIAG;
1194unsigned IOCTL_METEORCAPTUR = METEORCAPTUR;
1195unsigned IOCTL_METEORCAPFRM = METEORCAPFRM;
1196unsigned IOCTL_METEORSETGEO = METEORSETGEO;
1197unsigned IOCTL_METEORGETGEO = METEORGETGEO;
1198unsigned IOCTL_METEORSTATUS = METEORSTATUS;
1199unsigned IOCTL_METEORSHUE = METEORSHUE;
1200unsigned IOCTL_METEORGHUE = METEORGHUE;
1201unsigned IOCTL_METEORSFMT = METEORSFMT;
1202unsigned IOCTL_METEORGFMT = METEORGFMT;
1203unsigned IOCTL_METEORSINPUT = METEORSINPUT;
1204unsigned IOCTL_METEORGINPUT = METEORGINPUT;
1205unsigned IOCTL_METEORSCHCV = METEORSCHCV;
1206unsigned IOCTL_METEORGCHCV = METEORGCHCV;
1207unsigned IOCTL_METEORSCOUNT = METEORSCOUNT;
1208unsigned IOCTL_METEORGCOUNT = METEORGCOUNT;
1209unsigned IOCTL_METEORSFPS = METEORSFPS;
1210unsigned IOCTL_METEORGFPS = METEORGFPS;
1211unsigned IOCTL_METEORSSIGNAL = METEORSSIGNAL;
1212unsigned IOCTL_METEORGSIGNAL = METEORGSIGNAL;
1213unsigned IOCTL_METEORSVIDEO = METEORSVIDEO;
1214unsigned IOCTL_METEORGVIDEO = METEORGVIDEO;
1215unsigned IOCTL_METEORSBRIG = METEORSBRIG;
1216unsigned IOCTL_METEORGBRIG = METEORGBRIG;
1217unsigned IOCTL_METEORSCSAT = METEORSCSAT;
1218unsigned IOCTL_METEORGCSAT = METEORGCSAT;
1219unsigned IOCTL_METEORSCONT = METEORSCONT;
1220unsigned IOCTL_METEORGCONT = METEORGCONT;
1221unsigned IOCTL_METEORSHWS = METEORSHWS;
1222unsigned IOCTL_METEORGHWS = METEORGHWS;
1223unsigned IOCTL_METEORSVWS = METEORSVWS;
1224unsigned IOCTL_METEORGVWS = METEORGVWS;
1225unsigned IOCTL_METEORSTS = METEORSTS;
1226unsigned IOCTL_METEORGTS = METEORGTS;
1227unsigned IOCTL_TVTUNER_SETCHNL = TVTUNER_SETCHNL;
1228unsigned IOCTL_TVTUNER_GETCHNL = TVTUNER_GETCHNL;
1229unsigned IOCTL_TVTUNER_SETTYPE = TVTUNER_SETTYPE;
1230unsigned IOCTL_TVTUNER_GETTYPE = TVTUNER_GETTYPE;
1231unsigned IOCTL_TVTUNER_GETSTATUS = TVTUNER_GETSTATUS;
1232unsigned IOCTL_TVTUNER_SETFREQ = TVTUNER_SETFREQ;
1233unsigned IOCTL_TVTUNER_GETFREQ = TVTUNER_GETFREQ;
1234unsigned IOCTL_TVTUNER_SETAFC = TVTUNER_SETAFC;
1235unsigned IOCTL_TVTUNER_GETAFC = TVTUNER_GETAFC;
1236unsigned IOCTL_RADIO_SETMODE = RADIO_SETMODE;
1237unsigned IOCTL_RADIO_GETMODE = RADIO_GETMODE;
1238unsigned IOCTL_RADIO_SETFREQ = RADIO_SETFREQ;
1239unsigned IOCTL_RADIO_GETFREQ = RADIO_GETFREQ;
1240unsigned IOCTL_METEORSACTPIXFMT = METEORSACTPIXFMT;
1241unsigned IOCTL_METEORGACTPIXFMT = METEORGACTPIXFMT;
1242unsigned IOCTL_METEORGSUPPIXFMT = METEORGSUPPIXFMT;
1243unsigned IOCTL_TVTUNER_GETCHNLSET = TVTUNER_GETCHNLSET;
1244unsigned IOCTL_REMOTE_GETKEY = REMOTE_GETKEY;
1245unsigned IOCTL_GDT_IOCTL_GENERAL = GDT_IOCTL_GENERAL;
1246unsigned IOCTL_GDT_IOCTL_DRVERS = GDT_IOCTL_DRVERS;
1247unsigned IOCTL_GDT_IOCTL_CTRTYPE = GDT_IOCTL_CTRTYPE;
1248unsigned IOCTL_GDT_IOCTL_OSVERS = GDT_IOCTL_OSVERS;
1249unsigned IOCTL_GDT_IOCTL_CTRCNT = GDT_IOCTL_CTRCNT;
1250unsigned IOCTL_GDT_IOCTL_EVENT = GDT_IOCTL_EVENT;
1251unsigned IOCTL_GDT_IOCTL_STATIST = GDT_IOCTL_STATIST;
1252unsigned IOCTL_GDT_IOCTL_RESCAN = GDT_IOCTL_RESCAN;
1253unsigned IOCTL_ISP_SDBLEV = ISP_SDBLEV;
1254unsigned IOCTL_ISP_RESETHBA = ISP_RESETHBA;
1255unsigned IOCTL_ISP_RESCAN = ISP_RESCAN;
1256unsigned IOCTL_ISP_SETROLE = ISP_SETROLE;
1257unsigned IOCTL_ISP_GETROLE = ISP_GETROLE;
1258unsigned IOCTL_ISP_GET_STATS = ISP_GET_STATS;
1259unsigned IOCTL_ISP_CLR_STATS = ISP_CLR_STATS;
1260unsigned IOCTL_ISP_FC_LIP = ISP_FC_LIP;
1261unsigned IOCTL_ISP_FC_GETDINFO = ISP_FC_GETDINFO;
1262unsigned IOCTL_ISP_GET_FW_CRASH_DUMP = ISP_GET_FW_CRASH_DUMP;
1263unsigned IOCTL_ISP_FORCE_CRASH_DUMP = ISP_FORCE_CRASH_DUMP;
1264unsigned IOCTL_ISP_FC_GETHINFO = ISP_FC_GETHINFO;
1265unsigned IOCTL_ISP_TSK_MGMT = ISP_TSK_MGMT;
1266unsigned IOCTL_ISP_FC_GETDLIST = ISP_FC_GETDLIST;
1267unsigned IOCTL_MLXD_STATUS = MLXD_STATUS;
1268unsigned IOCTL_MLXD_CHECKASYNC = MLXD_CHECKASYNC;
1269unsigned IOCTL_MLXD_DETACH = MLXD_DETACH;
1270unsigned IOCTL_MLX_RESCAN_DRIVES = MLX_RESCAN_DRIVES;
1271unsigned IOCTL_MLX_PAUSE_CHANNEL = MLX_PAUSE_CHANNEL;
1272unsigned IOCTL_MLX_COMMAND = MLX_COMMAND;
1273unsigned IOCTL_MLX_REBUILDASYNC = MLX_REBUILDASYNC;
1274unsigned IOCTL_MLX_REBUILDSTAT = MLX_REBUILDSTAT;
1275unsigned IOCTL_MLX_GET_SYSDRIVE = MLX_GET_SYSDRIVE;
1276unsigned IOCTL_MLX_GET_CINFO = MLX_GET_CINFO;
1277unsigned IOCTL_NVME_PASSTHROUGH_CMD = NVME_PASSTHROUGH_CMD;
1278unsigned IOCTL_FWCFGIO_SET_INDEX = FWCFGIO_SET_INDEX;
1279unsigned IOCTL_IRDA_RESET_PARAMS = IRDA_RESET_PARAMS;
1280unsigned IOCTL_IRDA_SET_PARAMS = IRDA_SET_PARAMS;
1281unsigned IOCTL_IRDA_GET_SPEEDMASK = IRDA_GET_SPEEDMASK;
1282unsigned IOCTL_IRDA_GET_TURNAROUNDMASK = IRDA_GET_TURNAROUNDMASK;
1283unsigned IOCTL_IRFRAMETTY_GET_DEVICE = IRFRAMETTY_GET_DEVICE;
1284unsigned IOCTL_IRFRAMETTY_GET_DONGLE = IRFRAMETTY_GET_DONGLE;
1285unsigned IOCTL_IRFRAMETTY_SET_DONGLE = IRFRAMETTY_SET_DONGLE;
1286unsigned IOCTL_ISV_CMD = ISV_CMD;
1287unsigned IOCTL_WTQICMD = WTQICMD;
1288unsigned IOCTL_ISCSI_GET_VERSION = ISCSI_GET_VERSION;
1289unsigned IOCTL_ISCSI_LOGIN = ISCSI_LOGIN;
1290unsigned IOCTL_ISCSI_LOGOUT = ISCSI_LOGOUT;
1291unsigned IOCTL_ISCSI_ADD_CONNECTION = ISCSI_ADD_CONNECTION;
1292unsigned IOCTL_ISCSI_RESTORE_CONNECTION = ISCSI_RESTORE_CONNECTION;
1293unsigned IOCTL_ISCSI_REMOVE_CONNECTION = ISCSI_REMOVE_CONNECTION;
1294unsigned IOCTL_ISCSI_CONNECTION_STATUS = ISCSI_CONNECTION_STATUS;
1295unsigned IOCTL_ISCSI_SEND_TARGETS = ISCSI_SEND_TARGETS;
1296unsigned IOCTL_ISCSI_SET_NODE_NAME = ISCSI_SET_NODE_NAME;
1297unsigned IOCTL_ISCSI_IO_COMMAND = ISCSI_IO_COMMAND;
1298unsigned IOCTL_ISCSI_REGISTER_EVENT = ISCSI_REGISTER_EVENT;
1299unsigned IOCTL_ISCSI_DEREGISTER_EVENT = ISCSI_DEREGISTER_EVENT;
1300unsigned IOCTL_ISCSI_WAIT_EVENT = ISCSI_WAIT_EVENT;
1301unsigned IOCTL_ISCSI_POLL_EVENT = ISCSI_POLL_EVENT;
1302unsigned IOCTL_OFIOCGET = OFIOCGET;
1303unsigned IOCTL_OFIOCSET = OFIOCSET;
1304unsigned IOCTL_OFIOCNEXTPROP = OFIOCNEXTPROP;
1305unsigned IOCTL_OFIOCGETOPTNODE = OFIOCGETOPTNODE;
1306unsigned IOCTL_OFIOCGETNEXT = OFIOCGETNEXT;
1307unsigned IOCTL_OFIOCGETCHILD = OFIOCGETCHILD;
1308unsigned IOCTL_OFIOCFINDDEVICE = OFIOCFINDDEVICE;
1309unsigned IOCTL_AMR_IO_VERSION = AMR_IO_VERSION;
1310unsigned IOCTL_AMR_IO_COMMAND = AMR_IO_COMMAND;
1311unsigned IOCTL_MLYIO_COMMAND = MLYIO_COMMAND;
1312unsigned IOCTL_MLYIO_HEALTH = MLYIO_HEALTH;
1313unsigned IOCTL_PCI_IOC_CFGREAD = PCI_IOC_CFGREAD;
1314unsigned IOCTL_PCI_IOC_CFGWRITE = PCI_IOC_CFGWRITE;
1315unsigned IOCTL_PCI_IOC_BDF_CFGREAD = PCI_IOC_BDF_CFGREAD;
1316unsigned IOCTL_PCI_IOC_BDF_CFGWRITE = PCI_IOC_BDF_CFGWRITE;
1317unsigned IOCTL_PCI_IOC_BUSINFO = PCI_IOC_BUSINFO;
1318unsigned IOCTL_PCI_IOC_DRVNAME = PCI_IOC_DRVNAME;
1319unsigned IOCTL_PCI_IOC_DRVNAMEONBUS = PCI_IOC_DRVNAMEONBUS;
1320unsigned IOCTL_TWEIO_COMMAND = TWEIO_COMMAND;
1321unsigned IOCTL_TWEIO_STATS = TWEIO_STATS;
1322unsigned IOCTL_TWEIO_AEN_POLL = TWEIO_AEN_POLL;
1323unsigned IOCTL_TWEIO_AEN_WAIT = TWEIO_AEN_WAIT;
1324unsigned IOCTL_TWEIO_SET_PARAM = TWEIO_SET_PARAM;
1325unsigned IOCTL_TWEIO_GET_PARAM = TWEIO_GET_PARAM;
1326unsigned IOCTL_TWEIO_RESET = TWEIO_RESET;
1327unsigned IOCTL_TWEIO_ADD_UNIT = TWEIO_ADD_UNIT;
1328unsigned IOCTL_TWEIO_DEL_UNIT = TWEIO_DEL_UNIT;
1329unsigned IOCTL_SIOCSCNWDOMAIN = SIOCSCNWDOMAIN;
1330unsigned IOCTL_SIOCGCNWDOMAIN = SIOCGCNWDOMAIN;
1331unsigned IOCTL_SIOCSCNWKEY = SIOCSCNWKEY;
1332unsigned IOCTL_SIOCGCNWSTATUS = SIOCGCNWSTATUS;
1333unsigned IOCTL_SIOCGCNWSTATS = SIOCGCNWSTATS;
1334unsigned IOCTL_SIOCGCNWTRAIL = SIOCGCNWTRAIL;
1335unsigned IOCTL_SIOCGRAYSIGLEV = SIOCGRAYSIGLEV;
1336unsigned IOCTL_RAIDFRAME_SHUTDOWN = RAIDFRAME_SHUTDOWN;
1337unsigned IOCTL_RAIDFRAME_TUR = RAIDFRAME_TUR;
1338unsigned IOCTL_RAIDFRAME_FAIL_DISK = RAIDFRAME_FAIL_DISK;
1339unsigned IOCTL_RAIDFRAME_CHECK_RECON_STATUS = RAIDFRAME_CHECK_RECON_STATUS;
1340unsigned IOCTL_RAIDFRAME_REWRITEPARITY = RAIDFRAME_REWRITEPARITY;
1341unsigned IOCTL_RAIDFRAME_COPYBACK = RAIDFRAME_COPYBACK;
1342unsigned IOCTL_RAIDFRAME_SPARET_WAIT = RAIDFRAME_SPARET_WAIT;
1343unsigned IOCTL_RAIDFRAME_SEND_SPARET = RAIDFRAME_SEND_SPARET;
1344unsigned IOCTL_RAIDFRAME_ABORT_SPARET_WAIT = RAIDFRAME_ABORT_SPARET_WAIT;
1345unsigned IOCTL_RAIDFRAME_START_ATRACE = RAIDFRAME_START_ATRACE;
1346unsigned IOCTL_RAIDFRAME_STOP_ATRACE = RAIDFRAME_STOP_ATRACE;
1347unsigned IOCTL_RAIDFRAME_GET_SIZE = RAIDFRAME_GET_SIZE;
1348unsigned IOCTL_RAIDFRAME_RESET_ACCTOTALS = RAIDFRAME_RESET_ACCTOTALS;
1349unsigned IOCTL_RAIDFRAME_KEEP_ACCTOTALS = RAIDFRAME_KEEP_ACCTOTALS;
1350unsigned IOCTL_RAIDFRAME_GET_COMPONENT_LABEL = RAIDFRAME_GET_COMPONENT_LABEL;
1351unsigned IOCTL_RAIDFRAME_SET_COMPONENT_LABEL = RAIDFRAME_SET_COMPONENT_LABEL;
1352unsigned IOCTL_RAIDFRAME_INIT_LABELS = RAIDFRAME_INIT_LABELS;
1353unsigned IOCTL_RAIDFRAME_ADD_HOT_SPARE = RAIDFRAME_ADD_HOT_SPARE;
1354unsigned IOCTL_RAIDFRAME_REMOVE_HOT_SPARE = RAIDFRAME_REMOVE_HOT_SPARE;
1355unsigned IOCTL_RAIDFRAME_REBUILD_IN_PLACE = RAIDFRAME_REBUILD_IN_PLACE;
1356unsigned IOCTL_RAIDFRAME_CHECK_PARITY = RAIDFRAME_CHECK_PARITY;
1357unsigned IOCTL_RAIDFRAME_CHECK_PARITYREWRITE_STATUS =
1358 RAIDFRAME_CHECK_PARITYREWRITE_STATUS;
1359unsigned IOCTL_RAIDFRAME_CHECK_COPYBACK_STATUS =
1360 RAIDFRAME_CHECK_COPYBACK_STATUS;
1361unsigned IOCTL_RAIDFRAME_SET_AUTOCONFIG = RAIDFRAME_SET_AUTOCONFIG;
1362unsigned IOCTL_RAIDFRAME_SET_ROOT = RAIDFRAME_SET_ROOT;
1363unsigned IOCTL_RAIDFRAME_DELETE_COMPONENT = RAIDFRAME_DELETE_COMPONENT;
1364unsigned IOCTL_RAIDFRAME_INCORPORATE_HOT_SPARE =
1365 RAIDFRAME_INCORPORATE_HOT_SPARE;
1366unsigned IOCTL_RAIDFRAME_CHECK_RECON_STATUS_EXT =
1367 RAIDFRAME_CHECK_RECON_STATUS_EXT;
1368unsigned IOCTL_RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT =
1369 RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT;
1370unsigned IOCTL_RAIDFRAME_CHECK_COPYBACK_STATUS_EXT =
1371 RAIDFRAME_CHECK_COPYBACK_STATUS_EXT;
1372unsigned IOCTL_RAIDFRAME_CONFIGURE = RAIDFRAME_CONFIGURE;
1373unsigned IOCTL_RAIDFRAME_GET_INFO = RAIDFRAME_GET_INFO;
1374unsigned IOCTL_RAIDFRAME_PARITYMAP_STATUS = RAIDFRAME_PARITYMAP_STATUS;
1375unsigned IOCTL_RAIDFRAME_PARITYMAP_GET_DISABLE =
1376 RAIDFRAME_PARITYMAP_GET_DISABLE;
1377unsigned IOCTL_RAIDFRAME_PARITYMAP_SET_DISABLE =
1378 RAIDFRAME_PARITYMAP_SET_DISABLE;
1379unsigned IOCTL_RAIDFRAME_PARITYMAP_SET_PARAMS = RAIDFRAME_PARITYMAP_SET_PARAMS;
1380unsigned IOCTL_RAIDFRAME_SET_LAST_UNIT = RAIDFRAME_SET_LAST_UNIT;
1381unsigned IOCTL_MBPPIOCSPARAM = MBPPIOCSPARAM;
1382unsigned IOCTL_MBPPIOCGPARAM = MBPPIOCGPARAM;
1383unsigned IOCTL_MBPPIOCGSTAT = MBPPIOCGSTAT;
1384unsigned IOCTL_SESIOC_GETNOBJ = SESIOC_GETNOBJ;
1385unsigned IOCTL_SESIOC_GETOBJMAP = SESIOC_GETOBJMAP;
1386unsigned IOCTL_SESIOC_GETENCSTAT = SESIOC_GETENCSTAT;
1387unsigned IOCTL_SESIOC_SETENCSTAT = SESIOC_SETENCSTAT;
1388unsigned IOCTL_SESIOC_GETOBJSTAT = SESIOC_GETOBJSTAT;
1389unsigned IOCTL_SESIOC_SETOBJSTAT = SESIOC_SETOBJSTAT;
1390unsigned IOCTL_SESIOC_GETTEXT = SESIOC_GETTEXT;
1391unsigned IOCTL_SESIOC_INIT = SESIOC_INIT;
1392unsigned IOCTL_SUN_DKIOCGGEOM = SUN_DKIOCGGEOM;
1393unsigned IOCTL_SUN_DKIOCINFO = SUN_DKIOCINFO;
1394unsigned IOCTL_SUN_DKIOCGPART = SUN_DKIOCGPART;
1395unsigned IOCTL_FBIOGTYPE = FBIOGTYPE;
1396unsigned IOCTL_FBIOPUTCMAP = FBIOPUTCMAP;
1397unsigned IOCTL_FBIOGETCMAP = FBIOGETCMAP;
1398unsigned IOCTL_FBIOGATTR = FBIOGATTR;
1399unsigned IOCTL_FBIOSVIDEO = FBIOSVIDEO;
1400unsigned IOCTL_FBIOGVIDEO = FBIOGVIDEO;
1401unsigned IOCTL_FBIOSCURSOR = FBIOSCURSOR;
1402unsigned IOCTL_FBIOGCURSOR = FBIOGCURSOR;
1403unsigned IOCTL_FBIOSCURPOS = FBIOSCURPOS;
1404unsigned IOCTL_FBIOGCURPOS = FBIOGCURPOS;
1405unsigned IOCTL_FBIOGCURMAX = FBIOGCURMAX;
1406unsigned IOCTL_KIOCTRANS = KIOCTRANS;
1407unsigned IOCTL_KIOCSETKEY = KIOCSETKEY;
1408unsigned IOCTL_KIOCGETKEY = KIOCGETKEY;
1409unsigned IOCTL_KIOCGTRANS = KIOCGTRANS;
1410unsigned IOCTL_KIOCCMD = KIOCCMD;
1411unsigned IOCTL_KIOCTYPE = KIOCTYPE;
1412unsigned IOCTL_KIOCSDIRECT = KIOCSDIRECT;
1413unsigned IOCTL_KIOCSKEY = KIOCSKEY;
1414unsigned IOCTL_KIOCGKEY = KIOCGKEY;
1415unsigned IOCTL_KIOCSLED = KIOCSLED;
1416unsigned IOCTL_KIOCGLED = KIOCGLED;
1417unsigned IOCTL_KIOCLAYOUT = KIOCLAYOUT;
1418unsigned IOCTL_VUIDSFORMAT = VUIDSFORMAT;
1419unsigned IOCTL_VUIDGFORMAT = VUIDGFORMAT;
1420unsigned IOCTL_STICIO_GXINFO = STICIO_GXINFO;
1421unsigned IOCTL_STICIO_RESET = STICIO_RESET;
1422unsigned IOCTL_STICIO_STARTQ = STICIO_STARTQ;
1423unsigned IOCTL_STICIO_STOPQ = STICIO_STOPQ;
1424unsigned IOCTL_UKYOPON_IDENTIFY = UKYOPON_IDENTIFY;
1425unsigned IOCTL_URIO_SEND_COMMAND = URIO_SEND_COMMAND;
1426unsigned IOCTL_URIO_RECV_COMMAND = URIO_RECV_COMMAND;
1427unsigned IOCTL_USB_REQUEST = USB_REQUEST;
1428unsigned IOCTL_USB_SETDEBUG = USB_SETDEBUG;
1429unsigned IOCTL_USB_DISCOVER = USB_DISCOVER;
1430unsigned IOCTL_USB_DEVICEINFO = USB_DEVICEINFO;
1431unsigned IOCTL_USB_DEVICEINFO_OLD = USB_DEVICEINFO_OLD;
1432unsigned IOCTL_USB_DEVICESTATS = USB_DEVICESTATS;
1433unsigned IOCTL_USB_GET_REPORT_DESC = USB_GET_REPORT_DESC;
1434unsigned IOCTL_USB_SET_IMMED = USB_SET_IMMED;
1435unsigned IOCTL_USB_GET_REPORT = USB_GET_REPORT;
1436unsigned IOCTL_USB_SET_REPORT = USB_SET_REPORT;
1437unsigned IOCTL_USB_GET_REPORT_ID = USB_GET_REPORT_ID;
1438unsigned IOCTL_USB_GET_CONFIG = USB_GET_CONFIG;
1439unsigned IOCTL_USB_SET_CONFIG = USB_SET_CONFIG;
1440unsigned IOCTL_USB_GET_ALTINTERFACE = USB_GET_ALTINTERFACE;
1441unsigned IOCTL_USB_SET_ALTINTERFACE = USB_SET_ALTINTERFACE;
1442unsigned IOCTL_USB_GET_NO_ALT = USB_GET_NO_ALT;
1443unsigned IOCTL_USB_GET_DEVICE_DESC = USB_GET_DEVICE_DESC;
1444unsigned IOCTL_USB_GET_CONFIG_DESC = USB_GET_CONFIG_DESC;
1445unsigned IOCTL_USB_GET_INTERFACE_DESC = USB_GET_INTERFACE_DESC;
1446unsigned IOCTL_USB_GET_ENDPOINT_DESC = USB_GET_ENDPOINT_DESC;
1447unsigned IOCTL_USB_GET_FULL_DESC = USB_GET_FULL_DESC;
1448unsigned IOCTL_USB_GET_STRING_DESC = USB_GET_STRING_DESC;
1449unsigned IOCTL_USB_DO_REQUEST = USB_DO_REQUEST;
1450unsigned IOCTL_USB_GET_DEVICEINFO = USB_GET_DEVICEINFO;
1451unsigned IOCTL_USB_GET_DEVICEINFO_OLD = USB_GET_DEVICEINFO_OLD;
1452unsigned IOCTL_USB_SET_SHORT_XFER = USB_SET_SHORT_XFER;
1453unsigned IOCTL_USB_SET_TIMEOUT = USB_SET_TIMEOUT;
1454unsigned IOCTL_USB_SET_BULK_RA = USB_SET_BULK_RA;
1455unsigned IOCTL_USB_SET_BULK_WB = USB_SET_BULK_WB;
1456unsigned IOCTL_USB_SET_BULK_RA_OPT = USB_SET_BULK_RA_OPT;
1457unsigned IOCTL_USB_SET_BULK_WB_OPT = USB_SET_BULK_WB_OPT;
1458unsigned IOCTL_USB_GET_CM_OVER_DATA = USB_GET_CM_OVER_DATA;
1459unsigned IOCTL_USB_SET_CM_OVER_DATA = USB_SET_CM_OVER_DATA;
1460unsigned IOCTL_UTOPPYIOTURBO = UTOPPYIOTURBO;
1461unsigned IOCTL_UTOPPYIOCANCEL = UTOPPYIOCANCEL;
1462unsigned IOCTL_UTOPPYIOREBOOT = UTOPPYIOREBOOT;
1463unsigned IOCTL_UTOPPYIOSTATS = UTOPPYIOSTATS;
1464unsigned IOCTL_UTOPPYIORENAME = UTOPPYIORENAME;
1465unsigned IOCTL_UTOPPYIOMKDIR = UTOPPYIOMKDIR;
1466unsigned IOCTL_UTOPPYIODELETE = UTOPPYIODELETE;
1467unsigned IOCTL_UTOPPYIOREADDIR = UTOPPYIOREADDIR;
1468unsigned IOCTL_UTOPPYIOREADFILE = UTOPPYIOREADFILE;
1469unsigned IOCTL_UTOPPYIOWRITEFILE = UTOPPYIOWRITEFILE;
1470unsigned IOCTL_DIOSXDCMD = DIOSXDCMD;
1471unsigned IOCTL_VT_OPENQRY = VT_OPENQRY;
1472unsigned IOCTL_VT_SETMODE = VT_SETMODE;
1473unsigned IOCTL_VT_GETMODE = VT_GETMODE;
1474unsigned IOCTL_VT_RELDISP = VT_RELDISP;
1475unsigned IOCTL_VT_ACTIVATE = VT_ACTIVATE;
1476unsigned IOCTL_VT_WAITACTIVE = VT_WAITACTIVE;
1477unsigned IOCTL_VT_GETACTIVE = VT_GETACTIVE;
1478unsigned IOCTL_VT_GETSTATE = VT_GETSTATE;
1479unsigned IOCTL_KDGETKBENT = KDGETKBENT;
1480unsigned IOCTL_KDGKBMODE = KDGKBMODE;
1481unsigned IOCTL_KDSKBMODE = KDSKBMODE;
1482unsigned IOCTL_KDMKTONE = KDMKTONE;
1483unsigned IOCTL_KDSETMODE = KDSETMODE;
1484unsigned IOCTL_KDENABIO = KDENABIO;
1485unsigned IOCTL_KDDISABIO = KDDISABIO;
1486unsigned IOCTL_KDGKBTYPE = KDGKBTYPE;
1487unsigned IOCTL_KDGETLED = KDGETLED;
1488unsigned IOCTL_KDSETLED = KDSETLED;
1489unsigned IOCTL_KDSETRAD = KDSETRAD;
1490unsigned IOCTL_VGAPCVTID = VGAPCVTID;
1491unsigned IOCTL_CONS_GETVERS = CONS_GETVERS;
1492unsigned IOCTL_WSKBDIO_GTYPE = WSKBDIO_GTYPE;
1493unsigned IOCTL_WSKBDIO_BELL = WSKBDIO_BELL;
1494unsigned IOCTL_WSKBDIO_COMPLEXBELL = WSKBDIO_COMPLEXBELL;
1495unsigned IOCTL_WSKBDIO_SETBELL = WSKBDIO_SETBELL;
1496unsigned IOCTL_WSKBDIO_GETBELL = WSKBDIO_GETBELL;
1497unsigned IOCTL_WSKBDIO_SETDEFAULTBELL = WSKBDIO_SETDEFAULTBELL;
1498unsigned IOCTL_WSKBDIO_GETDEFAULTBELL = WSKBDIO_GETDEFAULTBELL;
1499unsigned IOCTL_WSKBDIO_SETKEYREPEAT = WSKBDIO_SETKEYREPEAT;
1500unsigned IOCTL_WSKBDIO_GETKEYREPEAT = WSKBDIO_GETKEYREPEAT;
1501unsigned IOCTL_WSKBDIO_SETDEFAULTKEYREPEAT = WSKBDIO_SETDEFAULTKEYREPEAT;
1502unsigned IOCTL_WSKBDIO_GETDEFAULTKEYREPEAT = WSKBDIO_GETDEFAULTKEYREPEAT;
1503unsigned IOCTL_WSKBDIO_SETLEDS = WSKBDIO_SETLEDS;
1504unsigned IOCTL_WSKBDIO_GETLEDS = WSKBDIO_GETLEDS;
1505unsigned IOCTL_WSKBDIO_GETMAP = WSKBDIO_GETMAP;
1506unsigned IOCTL_WSKBDIO_SETMAP = WSKBDIO_SETMAP;
1507unsigned IOCTL_WSKBDIO_GETENCODING = WSKBDIO_GETENCODING;
1508unsigned IOCTL_WSKBDIO_SETENCODING = WSKBDIO_SETENCODING;
1509unsigned IOCTL_WSKBDIO_SETMODE = WSKBDIO_SETMODE;
1510unsigned IOCTL_WSKBDIO_GETMODE = WSKBDIO_GETMODE;
1511unsigned IOCTL_WSKBDIO_SETKEYCLICK = WSKBDIO_SETKEYCLICK;
1512unsigned IOCTL_WSKBDIO_GETKEYCLICK = WSKBDIO_GETKEYCLICK;
1513unsigned IOCTL_WSKBDIO_GETSCROLL = WSKBDIO_GETSCROLL;
1514unsigned IOCTL_WSKBDIO_SETSCROLL = WSKBDIO_SETSCROLL;
1515unsigned IOCTL_WSKBDIO_SETVERSION = WSKBDIO_SETVERSION;
1516unsigned IOCTL_WSMOUSEIO_GTYPE = WSMOUSEIO_GTYPE;
1517unsigned IOCTL_WSMOUSEIO_SRES = WSMOUSEIO_SRES;
1518unsigned IOCTL_WSMOUSEIO_SSCALE = WSMOUSEIO_SSCALE;
1519unsigned IOCTL_WSMOUSEIO_SRATE = WSMOUSEIO_SRATE;
1520unsigned IOCTL_WSMOUSEIO_SCALIBCOORDS = WSMOUSEIO_SCALIBCOORDS;
1521unsigned IOCTL_WSMOUSEIO_GCALIBCOORDS = WSMOUSEIO_GCALIBCOORDS;
1522unsigned IOCTL_WSMOUSEIO_GETID = WSMOUSEIO_GETID;
1523unsigned IOCTL_WSMOUSEIO_GETREPEAT = WSMOUSEIO_GETREPEAT;
1524unsigned IOCTL_WSMOUSEIO_SETREPEAT = WSMOUSEIO_SETREPEAT;
1525unsigned IOCTL_WSMOUSEIO_SETVERSION = WSMOUSEIO_SETVERSION;
1526unsigned IOCTL_WSDISPLAYIO_GTYPE = WSDISPLAYIO_GTYPE;
1527unsigned IOCTL_WSDISPLAYIO_GINFO = WSDISPLAYIO_GINFO;
1528unsigned IOCTL_WSDISPLAYIO_GETCMAP = WSDISPLAYIO_GETCMAP;
1529unsigned IOCTL_WSDISPLAYIO_PUTCMAP = WSDISPLAYIO_PUTCMAP;
1530unsigned IOCTL_WSDISPLAYIO_GVIDEO = WSDISPLAYIO_GVIDEO;
1531unsigned IOCTL_WSDISPLAYIO_SVIDEO = WSDISPLAYIO_SVIDEO;
1532unsigned IOCTL_WSDISPLAYIO_GCURPOS = WSDISPLAYIO_GCURPOS;
1533unsigned IOCTL_WSDISPLAYIO_SCURPOS = WSDISPLAYIO_SCURPOS;
1534unsigned IOCTL_WSDISPLAYIO_GCURMAX = WSDISPLAYIO_GCURMAX;
1535unsigned IOCTL_WSDISPLAYIO_GCURSOR = WSDISPLAYIO_GCURSOR;
1536unsigned IOCTL_WSDISPLAYIO_SCURSOR = WSDISPLAYIO_SCURSOR;
1537unsigned IOCTL_WSDISPLAYIO_GMODE = WSDISPLAYIO_GMODE;
1538unsigned IOCTL_WSDISPLAYIO_SMODE = WSDISPLAYIO_SMODE;
1539unsigned IOCTL_WSDISPLAYIO_LDFONT = WSDISPLAYIO_LDFONT;
1540unsigned IOCTL_WSDISPLAYIO_ADDSCREEN = WSDISPLAYIO_ADDSCREEN;
1541unsigned IOCTL_WSDISPLAYIO_DELSCREEN = WSDISPLAYIO_DELSCREEN;
1542unsigned IOCTL_WSDISPLAYIO_SFONT = WSDISPLAYIO_SFONT;
1543unsigned IOCTL__O_WSDISPLAYIO_SETKEYBOARD = _O_WSDISPLAYIO_SETKEYBOARD;
1544unsigned IOCTL_WSDISPLAYIO_GETPARAM = WSDISPLAYIO_GETPARAM;
1545unsigned IOCTL_WSDISPLAYIO_SETPARAM = WSDISPLAYIO_SETPARAM;
1546unsigned IOCTL_WSDISPLAYIO_GETACTIVESCREEN = WSDISPLAYIO_GETACTIVESCREEN;
1547unsigned IOCTL_WSDISPLAYIO_GETWSCHAR = WSDISPLAYIO_GETWSCHAR;
1548unsigned IOCTL_WSDISPLAYIO_PUTWSCHAR = WSDISPLAYIO_PUTWSCHAR;
1549unsigned IOCTL_WSDISPLAYIO_DGSCROLL = WSDISPLAYIO_DGSCROLL;
1550unsigned IOCTL_WSDISPLAYIO_DSSCROLL = WSDISPLAYIO_DSSCROLL;
1551unsigned IOCTL_WSDISPLAYIO_GMSGATTRS = WSDISPLAYIO_GMSGATTRS;
1552unsigned IOCTL_WSDISPLAYIO_SMSGATTRS = WSDISPLAYIO_SMSGATTRS;
1553unsigned IOCTL_WSDISPLAYIO_GBORDER = WSDISPLAYIO_GBORDER;
1554unsigned IOCTL_WSDISPLAYIO_SBORDER = WSDISPLAYIO_SBORDER;
1555unsigned IOCTL_WSDISPLAYIO_SSPLASH = WSDISPLAYIO_SSPLASH;
1556unsigned IOCTL_WSDISPLAYIO_SPROGRESS = WSDISPLAYIO_SPROGRESS;
1557unsigned IOCTL_WSDISPLAYIO_LINEBYTES = WSDISPLAYIO_LINEBYTES;
1558unsigned IOCTL_WSDISPLAYIO_SETVERSION = WSDISPLAYIO_SETVERSION;
1559unsigned IOCTL_WSMUXIO_ADD_DEVICE = WSMUXIO_ADD_DEVICE;
1560unsigned IOCTL_WSMUXIO_REMOVE_DEVICE = WSMUXIO_REMOVE_DEVICE;
1561unsigned IOCTL_WSMUXIO_LIST_DEVICES = WSMUXIO_LIST_DEVICES;
1562unsigned IOCTL_WSMUXIO_INJECTEVENT = WSMUXIO_INJECTEVENT;
1563unsigned IOCTL_WSDISPLAYIO_GET_BUSID = WSDISPLAYIO_GET_BUSID;
1564unsigned IOCTL_WSDISPLAYIO_GET_EDID = WSDISPLAYIO_GET_EDID;
1565unsigned IOCTL_WSDISPLAYIO_SET_POLLING = WSDISPLAYIO_SET_POLLING;
1566unsigned IOCTL_WSDISPLAYIO_GET_FBINFO = WSDISPLAYIO_GET_FBINFO;
1567unsigned IOCTL_WSDISPLAYIO_DOBLIT = WSDISPLAYIO_DOBLIT;
1568unsigned IOCTL_WSDISPLAYIO_WAITBLIT = WSDISPLAYIO_WAITBLIT;
1569unsigned IOCTL_BIOCLOCATE = BIOCLOCATE;
1570unsigned IOCTL_BIOCINQ = BIOCINQ;
1571unsigned IOCTL_BIOCDISK_NOVOL = BIOCDISK_NOVOL;
1572unsigned IOCTL_BIOCDISK = BIOCDISK;
1573unsigned IOCTL_BIOCVOL = BIOCVOL;
1574unsigned IOCTL_BIOCALARM = BIOCALARM;
1575unsigned IOCTL_BIOCBLINK = BIOCBLINK;
1576unsigned IOCTL_BIOCSETSTATE = BIOCSETSTATE;
1577unsigned IOCTL_BIOCVOLOPS = BIOCVOLOPS;
1578unsigned IOCTL_MD_GETCONF = MD_GETCONF;
1579unsigned IOCTL_MD_SETCONF = MD_SETCONF;
1580unsigned IOCTL_CCDIOCSET = CCDIOCSET;
1581unsigned IOCTL_CCDIOCCLR = CCDIOCCLR;
1582unsigned IOCTL_CGDIOCSET = CGDIOCSET;
1583unsigned IOCTL_CGDIOCCLR = CGDIOCCLR;
1584unsigned IOCTL_CGDIOCGET = CGDIOCGET;
1585unsigned IOCTL_FSSIOCSET = FSSIOCSET;
1586unsigned IOCTL_FSSIOCGET = FSSIOCGET;
1587unsigned IOCTL_FSSIOCCLR = FSSIOCCLR;
1588unsigned IOCTL_FSSIOFSET = FSSIOFSET;
1589unsigned IOCTL_FSSIOFGET = FSSIOFGET;
1590unsigned IOCTL_BTDEV_ATTACH = BTDEV_ATTACH;
1591unsigned IOCTL_BTDEV_DETACH = BTDEV_DETACH;
1592unsigned IOCTL_BTSCO_GETINFO = BTSCO_GETINFO;
1593unsigned IOCTL_KTTCP_IO_SEND = KTTCP_IO_SEND;
1594unsigned IOCTL_KTTCP_IO_RECV = KTTCP_IO_RECV;
1595unsigned IOCTL_IOC_LOCKSTAT_GVERSION = IOC_LOCKSTAT_GVERSION;
1596unsigned IOCTL_IOC_LOCKSTAT_ENABLE = IOC_LOCKSTAT_ENABLE;
1597unsigned IOCTL_IOC_LOCKSTAT_DISABLE = IOC_LOCKSTAT_DISABLE;
1598unsigned IOCTL_VNDIOCSET = VNDIOCSET;
1599unsigned IOCTL_VNDIOCCLR = VNDIOCCLR;
1600unsigned IOCTL_VNDIOCGET = VNDIOCGET;
1601unsigned IOCTL_SPKRTONE = SPKRTONE;
1602unsigned IOCTL_SPKRTUNE = SPKRTUNE;
1603unsigned IOCTL_SPKRGETVOL = SPKRGETVOL;
1604unsigned IOCTL_SPKRSETVOL = SPKRSETVOL;
1605#if defined(__x86_64__)
1606unsigned IOCTL_NVMM_IOC_CAPABILITY = NVMM_IOC_CAPABILITY;
1607unsigned IOCTL_NVMM_IOC_MACHINE_CREATE = NVMM_IOC_MACHINE_CREATE;
1608unsigned IOCTL_NVMM_IOC_MACHINE_DESTROY = NVMM_IOC_MACHINE_DESTROY;
1609unsigned IOCTL_NVMM_IOC_MACHINE_CONFIGURE = NVMM_IOC_MACHINE_CONFIGURE;
1610unsigned IOCTL_NVMM_IOC_VCPU_CREATE = NVMM_IOC_VCPU_CREATE;
1611unsigned IOCTL_NVMM_IOC_VCPU_DESTROY = NVMM_IOC_VCPU_DESTROY;
1612unsigned IOCTL_NVMM_IOC_VCPU_CONFIGURE = NVMM_IOC_VCPU_CONFIGURE;
1613unsigned IOCTL_NVMM_IOC_VCPU_SETSTATE = NVMM_IOC_VCPU_SETSTATE;
1614unsigned IOCTL_NVMM_IOC_VCPU_GETSTATE = NVMM_IOC_VCPU_GETSTATE;
1615unsigned IOCTL_NVMM_IOC_VCPU_INJECT = NVMM_IOC_VCPU_INJECT;
1616unsigned IOCTL_NVMM_IOC_VCPU_RUN = NVMM_IOC_VCPU_RUN;
1617unsigned IOCTL_NVMM_IOC_GPA_MAP = NVMM_IOC_GPA_MAP;
1618unsigned IOCTL_NVMM_IOC_GPA_UNMAP = NVMM_IOC_GPA_UNMAP;
1619unsigned IOCTL_NVMM_IOC_HVA_MAP = NVMM_IOC_HVA_MAP;
1620unsigned IOCTL_NVMM_IOC_HVA_UNMAP = NVMM_IOC_HVA_UNMAP;
1621unsigned IOCTL_NVMM_IOC_CTL = NVMM_IOC_CTL;
1622#endif
1623unsigned IOCTL_SPI_IOCTL_CONFIGURE = SPI_IOCTL_CONFIGURE;
1624unsigned IOCTL_SPI_IOCTL_TRANSFER = SPI_IOCTL_TRANSFER;
1625unsigned IOCTL_AUTOFSREQUEST = AUTOFSREQUEST;
1626unsigned IOCTL_AUTOFSDONE = AUTOFSDONE;
1627unsigned IOCTL_BIOCGBLEN = BIOCGBLEN;
1628unsigned IOCTL_BIOCSBLEN = BIOCSBLEN;
1629unsigned IOCTL_BIOCSETF = BIOCSETF;
1630unsigned IOCTL_BIOCFLUSH = BIOCFLUSH;
1631unsigned IOCTL_BIOCPROMISC = BIOCPROMISC;
1632unsigned IOCTL_BIOCGDLT = BIOCGDLT;
1633unsigned IOCTL_BIOCGETIF = BIOCGETIF;
1634unsigned IOCTL_BIOCSETIF = BIOCSETIF;
1635unsigned IOCTL_BIOCGSTATS = BIOCGSTATS;
1636unsigned IOCTL_BIOCGSTATSOLD = BIOCGSTATSOLD;
1637unsigned IOCTL_BIOCIMMEDIATE = BIOCIMMEDIATE;
1638unsigned IOCTL_BIOCVERSION = BIOCVERSION;
1639unsigned IOCTL_BIOCSTCPF = BIOCSTCPF;
1640unsigned IOCTL_BIOCSUDPF = BIOCSUDPF;
1641unsigned IOCTL_BIOCGHDRCMPLT = BIOCGHDRCMPLT;
1642unsigned IOCTL_BIOCSHDRCMPLT = BIOCSHDRCMPLT;
1643unsigned IOCTL_BIOCSDLT = BIOCSDLT;
1644unsigned IOCTL_BIOCGDLTLIST = BIOCGDLTLIST;
1645unsigned IOCTL_BIOCGDIRECTION = BIOCGDIRECTION;
1646unsigned IOCTL_BIOCSDIRECTION = BIOCSDIRECTION;
1647unsigned IOCTL_BIOCSRTIMEOUT = BIOCSRTIMEOUT;
1648unsigned IOCTL_BIOCGRTIMEOUT = BIOCGRTIMEOUT;
1649unsigned IOCTL_BIOCGFEEDBACK = BIOCGFEEDBACK;
1650unsigned IOCTL_BIOCSFEEDBACK = BIOCSFEEDBACK;
1651unsigned IOCTL_GRESADDRS = GRESADDRS;
1652unsigned IOCTL_GRESADDRD = GRESADDRD;
1653unsigned IOCTL_GREGADDRS = GREGADDRS;
1654unsigned IOCTL_GREGADDRD = GREGADDRD;
1655unsigned IOCTL_GRESPROTO = GRESPROTO;
1656unsigned IOCTL_GREGPROTO = GREGPROTO;
1657unsigned IOCTL_GRESSOCK = GRESSOCK;
1658unsigned IOCTL_GREDSOCK = GREDSOCK;
1659unsigned IOCTL_PPPIOCGRAWIN = PPPIOCGRAWIN;
1660unsigned IOCTL_PPPIOCGFLAGS = PPPIOCGFLAGS;
1661unsigned IOCTL_PPPIOCSFLAGS = PPPIOCSFLAGS;
1662unsigned IOCTL_PPPIOCGASYNCMAP = PPPIOCGASYNCMAP;
1663unsigned IOCTL_PPPIOCSASYNCMAP = PPPIOCSASYNCMAP;
1664unsigned IOCTL_PPPIOCGUNIT = PPPIOCGUNIT;
1665unsigned IOCTL_PPPIOCGRASYNCMAP = PPPIOCGRASYNCMAP;
1666unsigned IOCTL_PPPIOCSRASYNCMAP = PPPIOCSRASYNCMAP;
1667unsigned IOCTL_PPPIOCGMRU = PPPIOCGMRU;
1668unsigned IOCTL_PPPIOCSMRU = PPPIOCSMRU;
1669unsigned IOCTL_PPPIOCSMAXCID = PPPIOCSMAXCID;
1670unsigned IOCTL_PPPIOCGXASYNCMAP = PPPIOCGXASYNCMAP;
1671unsigned IOCTL_PPPIOCSXASYNCMAP = PPPIOCSXASYNCMAP;
1672unsigned IOCTL_PPPIOCXFERUNIT = PPPIOCXFERUNIT;
1673unsigned IOCTL_PPPIOCSCOMPRESS = PPPIOCSCOMPRESS;
1674unsigned IOCTL_PPPIOCGNPMODE = PPPIOCGNPMODE;
1675unsigned IOCTL_PPPIOCSNPMODE = PPPIOCSNPMODE;
1676unsigned IOCTL_PPPIOCGIDLE = PPPIOCGIDLE;
1677unsigned IOCTL_PPPIOCGMTU = PPPIOCGMTU;
1678unsigned IOCTL_PPPIOCSMTU = PPPIOCSMTU;
1679unsigned IOCTL_SIOCGPPPSTATS = SIOCGPPPSTATS;
1680unsigned IOCTL_SIOCGPPPCSTATS = SIOCGPPPCSTATS;
1681unsigned IOCTL_IOC_NPF_VERSION = IOC_NPF_VERSION;
1682unsigned IOCTL_IOC_NPF_SWITCH = IOC_NPF_SWITCH;
1683unsigned IOCTL_IOC_NPF_LOAD = IOC_NPF_LOAD;
1684unsigned IOCTL_IOC_NPF_TABLE = IOC_NPF_TABLE;
1685unsigned IOCTL_IOC_NPF_STATS = IOC_NPF_STATS;
1686unsigned IOCTL_IOC_NPF_SAVE = IOC_NPF_SAVE;
1687unsigned IOCTL_IOC_NPF_RULE = IOC_NPF_RULE;
1688unsigned IOCTL_IOC_NPF_CONN_LOOKUP = IOC_NPF_CONN_LOOKUP;
1689unsigned IOCTL_IOC_NPF_TABLE_REPLACE = IOC_NPF_TABLE_REPLACE;
1690unsigned IOCTL_PPPOESETPARMS = PPPOESETPARMS;
1691unsigned IOCTL_PPPOEGETPARMS = PPPOEGETPARMS;
1692unsigned IOCTL_PPPOEGETSESSION = PPPOEGETSESSION;
1693unsigned IOCTL_SPPPGETAUTHCFG = SPPPGETAUTHCFG;
1694unsigned IOCTL_SPPPSETAUTHCFG = SPPPSETAUTHCFG;
1695unsigned IOCTL_SPPPGETLCPCFG = SPPPGETLCPCFG;
1696unsigned IOCTL_SPPPSETLCPCFG = SPPPSETLCPCFG;
1697unsigned IOCTL_SPPPGETSTATUS = SPPPGETSTATUS;
1698unsigned IOCTL_SPPPGETSTATUSNCP = SPPPGETSTATUSNCP;
1699unsigned IOCTL_SPPPGETIDLETO = SPPPGETIDLETO;
1700unsigned IOCTL_SPPPSETIDLETO = SPPPSETIDLETO;
1701unsigned IOCTL_SPPPGETAUTHFAILURES = SPPPGETAUTHFAILURES;
1702unsigned IOCTL_SPPPSETAUTHFAILURE = SPPPSETAUTHFAILURE;
1703unsigned IOCTL_SPPPSETDNSOPTS = SPPPSETDNSOPTS;
1704unsigned IOCTL_SPPPGETDNSOPTS = SPPPGETDNSOPTS;
1705unsigned IOCTL_SPPPGETDNSADDRS = SPPPGETDNSADDRS;
1706unsigned IOCTL_SPPPSETKEEPALIVE = SPPPSETKEEPALIVE;
1707unsigned IOCTL_SPPPGETKEEPALIVE = SPPPGETKEEPALIVE;
1708unsigned IOCTL_SRT_GETNRT = SRT_GETNRT;
1709unsigned IOCTL_SRT_GETRT = SRT_GETRT;
1710unsigned IOCTL_SRT_SETRT = SRT_SETRT;
1711unsigned IOCTL_SRT_DELRT = SRT_DELRT;
1712unsigned IOCTL_SRT_SFLAGS = SRT_SFLAGS;
1713unsigned IOCTL_SRT_GFLAGS = SRT_GFLAGS;
1714unsigned IOCTL_SRT_SGFLAGS = SRT_SGFLAGS;
1715unsigned IOCTL_SRT_DEBUG = SRT_DEBUG;
1716unsigned IOCTL_TAPGIFNAME = TAPGIFNAME;
1717unsigned IOCTL_TUNSDEBUG = TUNSDEBUG;
1718unsigned IOCTL_TUNGDEBUG = TUNGDEBUG;
1719unsigned IOCTL_TUNSIFMODE = TUNSIFMODE;
1720unsigned IOCTL_TUNSLMODE = TUNSLMODE;
1721unsigned IOCTL_TUNSIFHEAD = TUNSIFHEAD;
1722unsigned IOCTL_TUNGIFHEAD = TUNGIFHEAD;
1723unsigned IOCTL_DIOCSTART = DIOCSTART;
1724unsigned IOCTL_DIOCSTOP = DIOCSTOP;
1725unsigned IOCTL_DIOCADDRULE = DIOCADDRULE;
1726unsigned IOCTL_DIOCGETRULES = DIOCGETRULES;
1727unsigned IOCTL_DIOCGETRULE = DIOCGETRULE;
1728unsigned IOCTL_DIOCSETLCK = DIOCSETLCK;
1729unsigned IOCTL_DIOCCLRSTATES = DIOCCLRSTATES;
1730unsigned IOCTL_DIOCGETSTATE = DIOCGETSTATE;
1731unsigned IOCTL_DIOCSETSTATUSIF = DIOCSETSTATUSIF;
1732unsigned IOCTL_DIOCGETSTATUS = DIOCGETSTATUS;
1733unsigned IOCTL_DIOCCLRSTATUS = DIOCCLRSTATUS;
1734unsigned IOCTL_DIOCNATLOOK = DIOCNATLOOK;
1735unsigned IOCTL_DIOCSETDEBUG = DIOCSETDEBUG;
1736unsigned IOCTL_DIOCGETSTATES = DIOCGETSTATES;
1737unsigned IOCTL_DIOCCHANGERULE = DIOCCHANGERULE;
1738unsigned IOCTL_DIOCSETTIMEOUT = DIOCSETTIMEOUT;
1739unsigned IOCTL_DIOCGETTIMEOUT = DIOCGETTIMEOUT;
1740unsigned IOCTL_DIOCADDSTATE = DIOCADDSTATE;
1741unsigned IOCTL_DIOCCLRRULECTRS = DIOCCLRRULECTRS;
1742unsigned IOCTL_DIOCGETLIMIT = DIOCGETLIMIT;
1743unsigned IOCTL_DIOCSETLIMIT = DIOCSETLIMIT;
1744unsigned IOCTL_DIOCKILLSTATES = DIOCKILLSTATES;
1745unsigned IOCTL_DIOCSTARTALTQ = DIOCSTARTALTQ;
1746unsigned IOCTL_DIOCSTOPALTQ = DIOCSTOPALTQ;
1747unsigned IOCTL_DIOCADDALTQ = DIOCADDALTQ;
1748unsigned IOCTL_DIOCGETALTQS = DIOCGETALTQS;
1749unsigned IOCTL_DIOCGETALTQ = DIOCGETALTQ;
1750unsigned IOCTL_DIOCCHANGEALTQ = DIOCCHANGEALTQ;
1751unsigned IOCTL_DIOCGETQSTATS = DIOCGETQSTATS;
1752unsigned IOCTL_DIOCBEGINADDRS = DIOCBEGINADDRS;
1753unsigned IOCTL_DIOCADDADDR = DIOCADDADDR;
1754unsigned IOCTL_DIOCGETADDRS = DIOCGETADDRS;
1755unsigned IOCTL_DIOCGETADDR = DIOCGETADDR;
1756unsigned IOCTL_DIOCCHANGEADDR = DIOCCHANGEADDR;
1757unsigned IOCTL_DIOCADDSTATES = DIOCADDSTATES;
1758unsigned IOCTL_DIOCGETRULESETS = DIOCGETRULESETS;
1759unsigned IOCTL_DIOCGETRULESET = DIOCGETRULESET;
1760unsigned IOCTL_DIOCRCLRTABLES = DIOCRCLRTABLES;
1761unsigned IOCTL_DIOCRADDTABLES = DIOCRADDTABLES;
1762unsigned IOCTL_DIOCRDELTABLES = DIOCRDELTABLES;
1763unsigned IOCTL_DIOCRGETTABLES = DIOCRGETTABLES;
1764unsigned IOCTL_DIOCRGETTSTATS = DIOCRGETTSTATS;
1765unsigned IOCTL_DIOCRCLRTSTATS = DIOCRCLRTSTATS;
1766unsigned IOCTL_DIOCRCLRADDRS = DIOCRCLRADDRS;
1767unsigned IOCTL_DIOCRADDADDRS = DIOCRADDADDRS;
1768unsigned IOCTL_DIOCRDELADDRS = DIOCRDELADDRS;
1769unsigned IOCTL_DIOCRSETADDRS = DIOCRSETADDRS;
1770unsigned IOCTL_DIOCRGETADDRS = DIOCRGETADDRS;
1771unsigned IOCTL_DIOCRGETASTATS = DIOCRGETASTATS;
1772unsigned IOCTL_DIOCRCLRASTATS = DIOCRCLRASTATS;
1773unsigned IOCTL_DIOCRTSTADDRS = DIOCRTSTADDRS;
1774unsigned IOCTL_DIOCRSETTFLAGS = DIOCRSETTFLAGS;
1775unsigned IOCTL_DIOCRINADEFINE = DIOCRINADEFINE;
1776unsigned IOCTL_DIOCOSFPFLUSH = DIOCOSFPFLUSH;
1777unsigned IOCTL_DIOCOSFPADD = DIOCOSFPADD;
1778unsigned IOCTL_DIOCOSFPGET = DIOCOSFPGET;
1779unsigned IOCTL_DIOCXBEGIN = DIOCXBEGIN;
1780unsigned IOCTL_DIOCXCOMMIT = DIOCXCOMMIT;
1781unsigned IOCTL_DIOCXROLLBACK = DIOCXROLLBACK;
1782unsigned IOCTL_DIOCGETSRCNODES = DIOCGETSRCNODES;
1783unsigned IOCTL_DIOCCLRSRCNODES = DIOCCLRSRCNODES;
1784unsigned IOCTL_DIOCSETHOSTID = DIOCSETHOSTID;
1785unsigned IOCTL_DIOCIGETIFACES = DIOCIGETIFACES;
1786unsigned IOCTL_DIOCSETIFFLAG = DIOCSETIFFLAG;
1787unsigned IOCTL_DIOCCLRIFFLAG = DIOCCLRIFFLAG;
1788unsigned IOCTL_DIOCKILLSRCNODES = DIOCKILLSRCNODES;
1789unsigned IOCTL_SLIOCGUNIT = SLIOCGUNIT;
1790unsigned IOCTL_SIOCGBTINFO = SIOCGBTINFO;
1791unsigned IOCTL_SIOCGBTINFOA = SIOCGBTINFOA;
1792unsigned IOCTL_SIOCNBTINFO = SIOCNBTINFO;
1793unsigned IOCTL_SIOCSBTFLAGS = SIOCSBTFLAGS;
1794unsigned IOCTL_SIOCSBTPOLICY = SIOCSBTPOLICY;
1795unsigned IOCTL_SIOCSBTPTYPE = SIOCSBTPTYPE;
1796unsigned IOCTL_SIOCGBTSTATS = SIOCGBTSTATS;
1797unsigned IOCTL_SIOCZBTSTATS = SIOCZBTSTATS;
1798unsigned IOCTL_SIOCBTDUMP = SIOCBTDUMP;
1799unsigned IOCTL_SIOCSBTSCOMTU = SIOCSBTSCOMTU;
1800unsigned IOCTL_SIOCGBTFEAT = SIOCGBTFEAT;
1801unsigned IOCTL_SIOCADNAT = SIOCADNAT;
1802unsigned IOCTL_SIOCRMNAT = SIOCRMNAT;
1803unsigned IOCTL_SIOCGNATS = SIOCGNATS;
1804unsigned IOCTL_SIOCGNATL = SIOCGNATL;
1805unsigned IOCTL_SIOCPURGENAT = SIOCPURGENAT;
1806unsigned IOCTL_SIOCCONNECTX = SIOCCONNECTX;
1807unsigned IOCTL_SIOCCONNECTXDEL = SIOCCONNECTXDEL;
1808unsigned IOCTL_SIOCSIFINFO_FLAGS = SIOCSIFINFO_FLAGS;
1809unsigned IOCTL_SIOCAADDRCTL_POLICY = SIOCAADDRCTL_POLICY;
1810unsigned IOCTL_SIOCDADDRCTL_POLICY = SIOCDADDRCTL_POLICY;
1811unsigned IOCTL_SMBIOC_OPENSESSION = SMBIOC_OPENSESSION;
1812unsigned IOCTL_SMBIOC_OPENSHARE = SMBIOC_OPENSHARE;
1813unsigned IOCTL_SMBIOC_REQUEST = SMBIOC_REQUEST;
1814unsigned IOCTL_SMBIOC_SETFLAGS = SMBIOC_SETFLAGS;
1815unsigned IOCTL_SMBIOC_LOOKUP = SMBIOC_LOOKUP;
1816unsigned IOCTL_SMBIOC_READ = SMBIOC_READ;
1817unsigned IOCTL_SMBIOC_WRITE = SMBIOC_WRITE;
1818unsigned IOCTL_AGPIOC_INFO = AGPIOC_INFO;
1819unsigned IOCTL_AGPIOC_ACQUIRE = AGPIOC_ACQUIRE;
1820unsigned IOCTL_AGPIOC_RELEASE = AGPIOC_RELEASE;
1821unsigned IOCTL_AGPIOC_SETUP = AGPIOC_SETUP;
1822unsigned IOCTL_AGPIOC_ALLOCATE = AGPIOC_ALLOCATE;
1823unsigned IOCTL_AGPIOC_DEALLOCATE = AGPIOC_DEALLOCATE;
1824unsigned IOCTL_AGPIOC_BIND = AGPIOC_BIND;
1825unsigned IOCTL_AGPIOC_UNBIND = AGPIOC_UNBIND;
1826unsigned IOCTL_AUDIO_GETINFO = AUDIO_GETINFO;
1827unsigned IOCTL_AUDIO_SETINFO = AUDIO_SETINFO;
1828unsigned IOCTL_AUDIO_DRAIN = AUDIO_DRAIN;
1829unsigned IOCTL_AUDIO_FLUSH = AUDIO_FLUSH;
1830unsigned IOCTL_AUDIO_WSEEK = AUDIO_WSEEK;
1831unsigned IOCTL_AUDIO_RERROR = AUDIO_RERROR;
1832unsigned IOCTL_AUDIO_GETDEV = AUDIO_GETDEV;
1833unsigned IOCTL_AUDIO_GETENC = AUDIO_GETENC;
1834unsigned IOCTL_AUDIO_GETFD = AUDIO_GETFD;
1835unsigned IOCTL_AUDIO_SETFD = AUDIO_SETFD;
1836unsigned IOCTL_AUDIO_PERROR = AUDIO_PERROR;
1837unsigned IOCTL_AUDIO_GETIOFFS = AUDIO_GETIOFFS;
1838unsigned IOCTL_AUDIO_GETOOFFS = AUDIO_GETOOFFS;
1839unsigned IOCTL_AUDIO_GETPROPS = AUDIO_GETPROPS;
1840unsigned IOCTL_AUDIO_GETBUFINFO = AUDIO_GETBUFINFO;
1841unsigned IOCTL_AUDIO_SETCHAN = AUDIO_SETCHAN;
1842unsigned IOCTL_AUDIO_GETCHAN = AUDIO_GETCHAN;
1843unsigned IOCTL_AUDIO_QUERYFORMAT = AUDIO_QUERYFORMAT;
1844unsigned IOCTL_AUDIO_GETFORMAT = AUDIO_GETFORMAT;
1845unsigned IOCTL_AUDIO_SETFORMAT = AUDIO_SETFORMAT;
1846unsigned IOCTL_AUDIO_MIXER_READ = AUDIO_MIXER_READ;
1847unsigned IOCTL_AUDIO_MIXER_WRITE = AUDIO_MIXER_WRITE;
1848unsigned IOCTL_AUDIO_MIXER_DEVINFO = AUDIO_MIXER_DEVINFO;
1849unsigned IOCTL_ATAIOCCOMMAND = ATAIOCCOMMAND;
1850unsigned IOCTL_ATABUSIOSCAN = ATABUSIOSCAN;
1851unsigned IOCTL_ATABUSIORESET = ATABUSIORESET;
1852unsigned IOCTL_ATABUSIODETACH = ATABUSIODETACH;
1853unsigned IOCTL_CDIOCPLAYTRACKS = CDIOCPLAYTRACKS;
1854unsigned IOCTL_CDIOCPLAYBLOCKS = CDIOCPLAYBLOCKS;
1855unsigned IOCTL_CDIOCREADSUBCHANNEL = CDIOCREADSUBCHANNEL;
1856unsigned IOCTL_CDIOREADTOCHEADER = CDIOREADTOCHEADER;
1857unsigned IOCTL_CDIOREADTOCENTRIES = CDIOREADTOCENTRIES;
1858unsigned IOCTL_CDIOREADMSADDR = CDIOREADMSADDR;
1859unsigned IOCTL_CDIOCSETPATCH = CDIOCSETPATCH;
1860unsigned IOCTL_CDIOCGETVOL = CDIOCGETVOL;
1861unsigned IOCTL_CDIOCSETVOL = CDIOCSETVOL;
1862unsigned IOCTL_CDIOCSETMONO = CDIOCSETMONO;
1863unsigned IOCTL_CDIOCSETSTEREO = CDIOCSETSTEREO;
1864unsigned IOCTL_CDIOCSETMUTE = CDIOCSETMUTE;
1865unsigned IOCTL_CDIOCSETLEFT = CDIOCSETLEFT;
1866unsigned IOCTL_CDIOCSETRIGHT = CDIOCSETRIGHT;
1867unsigned IOCTL_CDIOCSETDEBUG = CDIOCSETDEBUG;
1868unsigned IOCTL_CDIOCCLRDEBUG = CDIOCCLRDEBUG;
1869unsigned IOCTL_CDIOCPAUSE = CDIOCPAUSE;
1870unsigned IOCTL_CDIOCRESUME = CDIOCRESUME;
1871unsigned IOCTL_CDIOCRESET = CDIOCRESET;
1872unsigned IOCTL_CDIOCSTART = CDIOCSTART;
1873unsigned IOCTL_CDIOCSTOP = CDIOCSTOP;
1874unsigned IOCTL_CDIOCEJECT = CDIOCEJECT;
1875unsigned IOCTL_CDIOCALLOW = CDIOCALLOW;
1876unsigned IOCTL_CDIOCPREVENT = CDIOCPREVENT;
1877unsigned IOCTL_CDIOCCLOSE = CDIOCCLOSE;
1878unsigned IOCTL_CDIOCPLAYMSF = CDIOCPLAYMSF;
1879unsigned IOCTL_CDIOCLOADUNLOAD = CDIOCLOADUNLOAD;
1880unsigned IOCTL_CHIOMOVE = CHIOMOVE;
1881unsigned IOCTL_CHIOEXCHANGE = CHIOEXCHANGE;
1882unsigned IOCTL_CHIOPOSITION = CHIOPOSITION;
1883unsigned IOCTL_CHIOGPICKER = CHIOGPICKER;
1884unsigned IOCTL_CHIOSPICKER = CHIOSPICKER;
1885unsigned IOCTL_CHIOGPARAMS = CHIOGPARAMS;
1886unsigned IOCTL_CHIOIELEM = CHIOIELEM;
1887unsigned IOCTL_OCHIOGSTATUS = OCHIOGSTATUS;
1888unsigned IOCTL_CHIOGSTATUS = CHIOGSTATUS;
1889unsigned IOCTL_CHIOSVOLTAG = CHIOSVOLTAG;
1890unsigned IOCTL_CLOCKCTL_SETTIMEOFDAY = CLOCKCTL_SETTIMEOFDAY;
1891unsigned IOCTL_CLOCKCTL_ADJTIME = CLOCKCTL_ADJTIME;
1892unsigned IOCTL_CLOCKCTL_CLOCK_SETTIME = CLOCKCTL_CLOCK_SETTIME;
1893unsigned IOCTL_CLOCKCTL_NTP_ADJTIME = CLOCKCTL_NTP_ADJTIME;
1894unsigned IOCTL_IOC_CPU_SETSTATE = IOC_CPU_SETSTATE;
1895unsigned IOCTL_IOC_CPU_GETSTATE = IOC_CPU_GETSTATE;
1896unsigned IOCTL_IOC_CPU_GETCOUNT = IOC_CPU_GETCOUNT;
1897unsigned IOCTL_IOC_CPU_MAPID = IOC_CPU_MAPID;
1898unsigned IOCTL_IOC_CPU_UCODE_GET_VERSION = IOC_CPU_UCODE_GET_VERSION;
1899unsigned IOCTL_IOC_CPU_UCODE_APPLY = IOC_CPU_UCODE_APPLY;
1900unsigned IOCTL_DIOCGDINFO = DIOCGDINFO;
1901unsigned IOCTL_DIOCSDINFO = DIOCSDINFO;
1902unsigned IOCTL_DIOCWDINFO = DIOCWDINFO;
1903unsigned IOCTL_DIOCRFORMAT = DIOCRFORMAT;
1904unsigned IOCTL_DIOCWFORMAT = DIOCWFORMAT;
1905unsigned IOCTL_DIOCSSTEP = DIOCSSTEP;
1906unsigned IOCTL_DIOCSRETRIES = DIOCSRETRIES;
1907unsigned IOCTL_DIOCKLABEL = DIOCKLABEL;
1908unsigned IOCTL_DIOCWLABEL = DIOCWLABEL;
1909unsigned IOCTL_DIOCSBAD = DIOCSBAD;
1910unsigned IOCTL_DIOCEJECT = DIOCEJECT;
1911unsigned IOCTL_ODIOCEJECT = ODIOCEJECT;
1912unsigned IOCTL_DIOCLOCK = DIOCLOCK;
1913unsigned IOCTL_DIOCGDEFLABEL = DIOCGDEFLABEL;
1914unsigned IOCTL_DIOCCLRLABEL = DIOCCLRLABEL;
1915unsigned IOCTL_DIOCGCACHE = DIOCGCACHE;
1916unsigned IOCTL_DIOCSCACHE = DIOCSCACHE;
1917unsigned IOCTL_DIOCCACHESYNC = DIOCCACHESYNC;
1918unsigned IOCTL_DIOCBSLIST = DIOCBSLIST;
1919unsigned IOCTL_DIOCBSFLUSH = DIOCBSFLUSH;
1920unsigned IOCTL_DIOCAWEDGE = DIOCAWEDGE;
1921unsigned IOCTL_DIOCGWEDGEINFO = DIOCGWEDGEINFO;
1922unsigned IOCTL_DIOCDWEDGE = DIOCDWEDGE;
1923unsigned IOCTL_DIOCLWEDGES = DIOCLWEDGES;
1924unsigned IOCTL_DIOCGSTRATEGY = DIOCGSTRATEGY;
1925unsigned IOCTL_DIOCSSTRATEGY = DIOCSSTRATEGY;
1926unsigned IOCTL_DIOCGDISKINFO = DIOCGDISKINFO;
1927unsigned IOCTL_DIOCTUR = DIOCTUR;
1928unsigned IOCTL_DIOCMWEDGES = DIOCMWEDGES;
1929unsigned IOCTL_DIOCGSECTORSIZE = DIOCGSECTORSIZE;
1930unsigned IOCTL_DIOCGMEDIASIZE = DIOCGMEDIASIZE;
1931unsigned IOCTL_DIOCRMWEDGES = DIOCRMWEDGES;
1932unsigned IOCTL_DRVDETACHDEV = DRVDETACHDEV;
1933unsigned IOCTL_DRVRESCANBUS = DRVRESCANBUS;
1934unsigned IOCTL_DRVCTLCOMMAND = DRVCTLCOMMAND;
1935unsigned IOCTL_DRVRESUMEDEV = DRVRESUMEDEV;
1936unsigned IOCTL_DRVLISTDEV = DRVLISTDEV;
1937unsigned IOCTL_DRVGETEVENT = DRVGETEVENT;
1938unsigned IOCTL_DRVSUSPENDDEV = DRVSUSPENDDEV;
1939unsigned IOCTL_DVD_READ_STRUCT = DVD_READ_STRUCT;
1940unsigned IOCTL_DVD_WRITE_STRUCT = DVD_WRITE_STRUCT;
1941unsigned IOCTL_DVD_AUTH = DVD_AUTH;
1942unsigned IOCTL_ENVSYS_GETDICTIONARY = ENVSYS_GETDICTIONARY;
1943unsigned IOCTL_ENVSYS_SETDICTIONARY = ENVSYS_SETDICTIONARY;
1944unsigned IOCTL_ENVSYS_REMOVEPROPS = ENVSYS_REMOVEPROPS;
1945unsigned IOCTL_ENVSYS_GTREDATA = ENVSYS_GTREDATA;
1946unsigned IOCTL_ENVSYS_GTREINFO = ENVSYS_GTREINFO;
1947unsigned IOCTL_KFILTER_BYFILTER = KFILTER_BYFILTER;
1948unsigned IOCTL_KFILTER_BYNAME = KFILTER_BYNAME;
1949unsigned IOCTL_FDIOCGETOPTS = FDIOCGETOPTS;
1950unsigned IOCTL_FDIOCSETOPTS = FDIOCSETOPTS;
1951unsigned IOCTL_FDIOCSETFORMAT = FDIOCSETFORMAT;
1952unsigned IOCTL_FDIOCGETFORMAT = FDIOCGETFORMAT;
1953unsigned IOCTL_FDIOCFORMAT_TRACK = FDIOCFORMAT_TRACK;
1954unsigned IOCTL_FIOCLEX = FIOCLEX;
1955unsigned IOCTL_FIONCLEX = FIONCLEX;
1956unsigned IOCTL_FIOSEEKDATA = FIOSEEKDATA;
1957unsigned IOCTL_FIOSEEKHOLE = FIOSEEKHOLE;
1958unsigned IOCTL_FIONREAD = FIONREAD;
1959unsigned IOCTL_FIONBIO = FIONBIO;
1960unsigned IOCTL_FIOASYNC = FIOASYNC;
1961unsigned IOCTL_FIOSETOWN = FIOSETOWN;
1962unsigned IOCTL_FIOGETOWN = FIOGETOWN;
1963unsigned IOCTL_OFIOGETBMAP = OFIOGETBMAP;
1964unsigned IOCTL_FIOGETBMAP = FIOGETBMAP;
1965unsigned IOCTL_FIONWRITE = FIONWRITE;
1966unsigned IOCTL_FIONSPACE = FIONSPACE;
1967unsigned IOCTL_GPIOINFO = GPIOINFO;
1968unsigned IOCTL_GPIOSET = GPIOSET;
1969unsigned IOCTL_GPIOUNSET = GPIOUNSET;
1970unsigned IOCTL_GPIOREAD = GPIOREAD;
1971unsigned IOCTL_GPIOWRITE = GPIOWRITE;
1972unsigned IOCTL_GPIOTOGGLE = GPIOTOGGLE;
1973unsigned IOCTL_GPIOATTACH = GPIOATTACH;
1974unsigned IOCTL_PTIOCNETBSD = PTIOCNETBSD;
1975unsigned IOCTL_PTIOCSUNOS = PTIOCSUNOS;
1976unsigned IOCTL_PTIOCLINUX = PTIOCLINUX;
1977unsigned IOCTL_PTIOCFREEBSD = PTIOCFREEBSD;
1978unsigned IOCTL_PTIOCULTRIX = PTIOCULTRIX;
1979unsigned IOCTL_TIOCHPCL = TIOCHPCL;
1980unsigned IOCTL_TIOCGETP = TIOCGETP;
1981unsigned IOCTL_TIOCSETP = TIOCSETP;
1982unsigned IOCTL_TIOCSETN = TIOCSETN;
1983unsigned IOCTL_TIOCSETC = TIOCSETC;
1984unsigned IOCTL_TIOCGETC = TIOCGETC;
1985unsigned IOCTL_TIOCLBIS = TIOCLBIS;
1986unsigned IOCTL_TIOCLBIC = TIOCLBIC;
1987unsigned IOCTL_TIOCLSET = TIOCLSET;
1988unsigned IOCTL_TIOCLGET = TIOCLGET;
1989unsigned IOCTL_TIOCSLTC = TIOCSLTC;
1990unsigned IOCTL_TIOCGLTC = TIOCGLTC;
1991unsigned IOCTL_OTIOCCONS = OTIOCCONS;
1992unsigned IOCTL_JOY_SETTIMEOUT = JOY_SETTIMEOUT;
1993unsigned IOCTL_JOY_GETTIMEOUT = JOY_GETTIMEOUT;
1994unsigned IOCTL_JOY_SET_X_OFFSET = JOY_SET_X_OFFSET;
1995unsigned IOCTL_JOY_SET_Y_OFFSET = JOY_SET_Y_OFFSET;
1996unsigned IOCTL_JOY_GET_X_OFFSET = JOY_GET_X_OFFSET;
1997unsigned IOCTL_JOY_GET_Y_OFFSET = JOY_GET_Y_OFFSET;
1998unsigned IOCTL_OKIOCGSYMBOL = OKIOCGSYMBOL;
1999unsigned IOCTL_OKIOCGVALUE = OKIOCGVALUE;
2000unsigned IOCTL_KIOCGSIZE = KIOCGSIZE;
2001unsigned IOCTL_KIOCGVALUE = KIOCGVALUE;
2002unsigned IOCTL_KIOCGSYMBOL = KIOCGSYMBOL;
2003unsigned IOCTL_LUAINFO = LUAINFO;
2004unsigned IOCTL_LUACREATE = LUACREATE;
2005unsigned IOCTL_LUADESTROY = LUADESTROY;
2006unsigned IOCTL_LUAREQUIRE = LUAREQUIRE;
2007unsigned IOCTL_LUALOAD = LUALOAD;
2008unsigned IOCTL_MIDI_PRETIME = MIDI_PRETIME;
2009unsigned IOCTL_MIDI_MPUMODE = MIDI_MPUMODE;
2010unsigned IOCTL_MIDI_MPUCMD = MIDI_MPUCMD;
2011unsigned IOCTL_SEQUENCER_RESET = SEQUENCER_RESET;
2012unsigned IOCTL_SEQUENCER_SYNC = SEQUENCER_SYNC;
2013unsigned IOCTL_SEQUENCER_INFO = SEQUENCER_INFO;
2014unsigned IOCTL_SEQUENCER_CTRLRATE = SEQUENCER_CTRLRATE;
2015unsigned IOCTL_SEQUENCER_GETOUTCOUNT = SEQUENCER_GETOUTCOUNT;
2016unsigned IOCTL_SEQUENCER_GETINCOUNT = SEQUENCER_GETINCOUNT;
2017unsigned IOCTL_SEQUENCER_RESETSAMPLES = SEQUENCER_RESETSAMPLES;
2018unsigned IOCTL_SEQUENCER_NRSYNTHS = SEQUENCER_NRSYNTHS;
2019unsigned IOCTL_SEQUENCER_NRMIDIS = SEQUENCER_NRMIDIS;
2020unsigned IOCTL_SEQUENCER_THRESHOLD = SEQUENCER_THRESHOLD;
2021unsigned IOCTL_SEQUENCER_MEMAVL = SEQUENCER_MEMAVL;
2022unsigned IOCTL_SEQUENCER_PANIC = SEQUENCER_PANIC;
2023unsigned IOCTL_SEQUENCER_OUTOFBAND = SEQUENCER_OUTOFBAND;
2024unsigned IOCTL_SEQUENCER_GETTIME = SEQUENCER_GETTIME;
2025unsigned IOCTL_SEQUENCER_TMR_TIMEBASE = SEQUENCER_TMR_TIMEBASE;
2026unsigned IOCTL_SEQUENCER_TMR_START = SEQUENCER_TMR_START;
2027unsigned IOCTL_SEQUENCER_TMR_STOP = SEQUENCER_TMR_STOP;
2028unsigned IOCTL_SEQUENCER_TMR_CONTINUE = SEQUENCER_TMR_CONTINUE;
2029unsigned IOCTL_SEQUENCER_TMR_TEMPO = SEQUENCER_TMR_TEMPO;
2030unsigned IOCTL_SEQUENCER_TMR_SOURCE = SEQUENCER_TMR_SOURCE;
2031unsigned IOCTL_SEQUENCER_TMR_METRONOME = SEQUENCER_TMR_METRONOME;
2032unsigned IOCTL_SEQUENCER_TMR_SELECT = SEQUENCER_TMR_SELECT;
2033unsigned IOCTL_MTIOCTOP = MTIOCTOP;
2034unsigned IOCTL_MTIOCGET = MTIOCGET;
2035unsigned IOCTL_MTIOCIEOT = MTIOCIEOT;
2036unsigned IOCTL_MTIOCEEOT = MTIOCEEOT;
2037unsigned IOCTL_MTIOCRDSPOS = MTIOCRDSPOS;
2038unsigned IOCTL_MTIOCRDHPOS = MTIOCRDHPOS;
2039unsigned IOCTL_MTIOCSLOCATE = MTIOCSLOCATE;
2040unsigned IOCTL_MTIOCHLOCATE = MTIOCHLOCATE;
2041unsigned IOCTL_POWER_EVENT_RECVDICT = POWER_EVENT_RECVDICT;
2042unsigned IOCTL_POWER_IOC_GET_TYPE = POWER_IOC_GET_TYPE;
2043unsigned IOCTL_RIOCGINFO = RIOCGINFO;
2044unsigned IOCTL_RIOCSINFO = RIOCSINFO;
2045unsigned IOCTL_RIOCSSRCH = RIOCSSRCH;
2046unsigned IOCTL_RNDGETENTCNT = RNDGETENTCNT;
2047unsigned IOCTL_RNDGETSRCNUM = RNDGETSRCNUM;
2048unsigned IOCTL_RNDGETSRCNAME = RNDGETSRCNAME;
2049unsigned IOCTL_RNDCTL = RNDCTL;
2050unsigned IOCTL_RNDADDDATA = RNDADDDATA;
2051unsigned IOCTL_RNDGETPOOLSTAT = RNDGETPOOLSTAT;
2052unsigned IOCTL_RNDGETESTNUM = RNDGETESTNUM;
2053unsigned IOCTL_RNDGETESTNAME = RNDGETESTNAME;
2054unsigned IOCTL_SCIOCGET = SCIOCGET;
2055unsigned IOCTL_SCIOCSET = SCIOCSET;
2056unsigned IOCTL_SCIOCRESTART = SCIOCRESTART;
2057unsigned IOCTL_SCIOC_USE_ADF = SCIOC_USE_ADF;
2058unsigned IOCTL_SCIOCCOMMAND = SCIOCCOMMAND;
2059unsigned IOCTL_SCIOCDEBUG = SCIOCDEBUG;
2060unsigned IOCTL_SCIOCIDENTIFY = SCIOCIDENTIFY;
2061unsigned IOCTL_OSCIOCIDENTIFY = OSCIOCIDENTIFY;
2062unsigned IOCTL_SCIOCDECONFIG = SCIOCDECONFIG;
2063unsigned IOCTL_SCIOCRECONFIG = SCIOCRECONFIG;
2064unsigned IOCTL_SCIOCRESET = SCIOCRESET;
2065unsigned IOCTL_SCBUSIOSCAN = SCBUSIOSCAN;
2066unsigned IOCTL_SCBUSIORESET = SCBUSIORESET;
2067unsigned IOCTL_SCBUSIODETACH = SCBUSIODETACH;
2068unsigned IOCTL_SCBUSACCEL = SCBUSACCEL;
2069unsigned IOCTL_SCBUSIOLLSCAN = SCBUSIOLLSCAN;
2070unsigned IOCTL_SIOCSHIWAT = SIOCSHIWAT;
2071unsigned IOCTL_SIOCGHIWAT = SIOCGHIWAT;
2072unsigned IOCTL_SIOCSLOWAT = SIOCSLOWAT;
2073unsigned IOCTL_SIOCGLOWAT = SIOCGLOWAT;
2074unsigned IOCTL_SIOCATMARK = SIOCATMARK;
2075unsigned IOCTL_SIOCSPGRP = SIOCSPGRP;
2076unsigned IOCTL_SIOCGPGRP = SIOCGPGRP;
2077unsigned IOCTL_SIOCPEELOFF = SIOCPEELOFF;
2078unsigned IOCTL_SIOCADDRT = SIOCADDRT;
2079unsigned IOCTL_SIOCDELRT = SIOCDELRT;
2080unsigned IOCTL_SIOCSIFADDR = SIOCSIFADDR;
2081unsigned IOCTL_SIOCGIFADDR = SIOCGIFADDR;
2082unsigned IOCTL_SIOCSIFDSTADDR = SIOCSIFDSTADDR;
2083unsigned IOCTL_SIOCGIFDSTADDR = SIOCGIFDSTADDR;
2084unsigned IOCTL_SIOCSIFFLAGS = SIOCSIFFLAGS;
2085unsigned IOCTL_SIOCGIFFLAGS = SIOCGIFFLAGS;
2086unsigned IOCTL_SIOCGIFBRDADDR = SIOCGIFBRDADDR;
2087unsigned IOCTL_SIOCSIFBRDADDR = SIOCSIFBRDADDR;
2088unsigned IOCTL_SIOCGIFCONF = SIOCGIFCONF;
2089unsigned IOCTL_SIOCGIFNETMASK = SIOCGIFNETMASK;
2090unsigned IOCTL_SIOCSIFNETMASK = SIOCSIFNETMASK;
2091unsigned IOCTL_SIOCGIFMETRIC = SIOCGIFMETRIC;
2092unsigned IOCTL_SIOCSIFMETRIC = SIOCSIFMETRIC;
2093unsigned IOCTL_SIOCDIFADDR = SIOCDIFADDR;
2094unsigned IOCTL_SIOCAIFADDR = SIOCAIFADDR;
2095unsigned IOCTL_SIOCGIFALIAS = SIOCGIFALIAS;
2096unsigned IOCTL_SIOCGIFAFLAG_IN = SIOCGIFAFLAG_IN;
2097unsigned IOCTL_SIOCALIFADDR = SIOCALIFADDR;
2098unsigned IOCTL_SIOCGLIFADDR = SIOCGLIFADDR;
2099unsigned IOCTL_SIOCDLIFADDR = SIOCDLIFADDR;
2100unsigned IOCTL_SIOCSIFADDRPREF = SIOCSIFADDRPREF;
2101unsigned IOCTL_SIOCGIFADDRPREF = SIOCGIFADDRPREF;
2102unsigned IOCTL_SIOCADDMULTI = SIOCADDMULTI;
2103unsigned IOCTL_SIOCDELMULTI = SIOCDELMULTI;
2104unsigned IOCTL_SIOCGETVIFCNT = SIOCGETVIFCNT;
2105unsigned IOCTL_SIOCGETSGCNT = SIOCGETSGCNT;
2106unsigned IOCTL_SIOCSIFMEDIA = SIOCSIFMEDIA;
2107unsigned IOCTL_SIOCGIFMEDIA = SIOCGIFMEDIA;
2108unsigned IOCTL_SIOCSIFGENERIC = SIOCSIFGENERIC;
2109unsigned IOCTL_SIOCGIFGENERIC = SIOCGIFGENERIC;
2110unsigned IOCTL_SIOCSIFPHYADDR = SIOCSIFPHYADDR;
2111unsigned IOCTL_SIOCGIFPSRCADDR = SIOCGIFPSRCADDR;
2112unsigned IOCTL_SIOCGIFPDSTADDR = SIOCGIFPDSTADDR;
2113unsigned IOCTL_SIOCDIFPHYADDR = SIOCDIFPHYADDR;
2114unsigned IOCTL_SIOCSLIFPHYADDR = SIOCSLIFPHYADDR;
2115unsigned IOCTL_SIOCGLIFPHYADDR = SIOCGLIFPHYADDR;
2116unsigned IOCTL_SIOCSIFMTU = SIOCSIFMTU;
2117unsigned IOCTL_SIOCGIFMTU = SIOCGIFMTU;
2118unsigned IOCTL_SIOCSDRVSPEC = SIOCSDRVSPEC;
2119unsigned IOCTL_SIOCGDRVSPEC = SIOCGDRVSPEC;
2120unsigned IOCTL_SIOCIFCREATE = SIOCIFCREATE;
2121unsigned IOCTL_SIOCIFDESTROY = SIOCIFDESTROY;
2122unsigned IOCTL_SIOCIFGCLONERS = SIOCIFGCLONERS;
2123unsigned IOCTL_SIOCGIFDLT = SIOCGIFDLT;
2124unsigned IOCTL_SIOCGIFCAP = SIOCGIFCAP;
2125unsigned IOCTL_SIOCSIFCAP = SIOCSIFCAP;
2126unsigned IOCTL_SIOCSVH = SIOCSVH;
2127unsigned IOCTL_SIOCGVH = SIOCGVH;
2128unsigned IOCTL_SIOCINITIFADDR = SIOCINITIFADDR;
2129unsigned IOCTL_SIOCGIFDATA = SIOCGIFDATA;
2130unsigned IOCTL_SIOCZIFDATA = SIOCZIFDATA;
2131unsigned IOCTL_SIOCGLINKSTR = SIOCGLINKSTR;
2132unsigned IOCTL_SIOCSLINKSTR = SIOCSLINKSTR;
2133unsigned IOCTL_SIOCGETHERCAP = SIOCGETHERCAP;
2134unsigned IOCTL_SIOCGIFINDEX = SIOCGIFINDEX;
2135unsigned IOCTL_SIOCSETHERCAP = SIOCSETHERCAP;
2136unsigned IOCTL_SIOCSIFDESCR = SIOCSIFDESCR;
2137unsigned IOCTL_SIOCGIFDESCR = SIOCGIFDESCR;
2138unsigned IOCTL_SIOCGUMBINFO = SIOCGUMBINFO;
2139unsigned IOCTL_SIOCSUMBPARAM = SIOCSUMBPARAM;
2140unsigned IOCTL_SIOCGUMBPARAM = SIOCGUMBPARAM;
2141unsigned IOCTL_SIOCSETPFSYNC = SIOCSETPFSYNC;
2142unsigned IOCTL_SIOCGETPFSYNC = SIOCGETPFSYNC;
2143unsigned IOCTL_PPS_IOC_CREATE = PPS_IOC_CREATE;
2144unsigned IOCTL_PPS_IOC_DESTROY = PPS_IOC_DESTROY;
2145unsigned IOCTL_PPS_IOC_SETPARAMS = PPS_IOC_SETPARAMS;
2146unsigned IOCTL_PPS_IOC_GETPARAMS = PPS_IOC_GETPARAMS;
2147unsigned IOCTL_PPS_IOC_GETCAP = PPS_IOC_GETCAP;
2148unsigned IOCTL_PPS_IOC_FETCH = PPS_IOC_FETCH;
2149unsigned IOCTL_PPS_IOC_KCBIND = PPS_IOC_KCBIND;
2150unsigned IOCTL_TIOCEXCL = TIOCEXCL;
2151unsigned IOCTL_TIOCNXCL = TIOCNXCL;
2152unsigned IOCTL_TIOCFLUSH = TIOCFLUSH;
2153unsigned IOCTL_TIOCGETA = TIOCGETA;
2154unsigned IOCTL_TIOCSETA = TIOCSETA;
2155unsigned IOCTL_TIOCSETAW = TIOCSETAW;
2156unsigned IOCTL_TIOCSETAF = TIOCSETAF;
2157unsigned IOCTL_TIOCGETD = TIOCGETD;
2158unsigned IOCTL_TIOCSETD = TIOCSETD;
2159unsigned IOCTL_TIOCGLINED = TIOCGLINED;
2160unsigned IOCTL_TIOCSLINED = TIOCSLINED;
2161unsigned IOCTL_TIOCSBRK = TIOCSBRK;
2162unsigned IOCTL_TIOCCBRK = TIOCCBRK;
2163unsigned IOCTL_TIOCSDTR = TIOCSDTR;
2164unsigned IOCTL_TIOCCDTR = TIOCCDTR;
2165unsigned IOCTL_TIOCGPGRP = TIOCGPGRP;
2166unsigned IOCTL_TIOCSPGRP = TIOCSPGRP;
2167unsigned IOCTL_TIOCOUTQ = TIOCOUTQ;
2168unsigned IOCTL_TIOCSTI = TIOCSTI;
2169unsigned IOCTL_TIOCNOTTY = TIOCNOTTY;
2170unsigned IOCTL_TIOCPKT = TIOCPKT;
2171unsigned IOCTL_TIOCSTOP = TIOCSTOP;
2172unsigned IOCTL_TIOCSTART = TIOCSTART;
2173unsigned IOCTL_TIOCMSET = TIOCMSET;
2174unsigned IOCTL_TIOCMBIS = TIOCMBIS;
2175unsigned IOCTL_TIOCMBIC = TIOCMBIC;
2176unsigned IOCTL_TIOCMGET = TIOCMGET;
2177unsigned IOCTL_TIOCREMOTE = TIOCREMOTE;
2178unsigned IOCTL_TIOCGWINSZ = TIOCGWINSZ;
2179unsigned IOCTL_TIOCSWINSZ = TIOCSWINSZ;
2180unsigned IOCTL_TIOCUCNTL = TIOCUCNTL;
2181unsigned IOCTL_TIOCSTAT = TIOCSTAT;
2182unsigned IOCTL_TIOCGSID = TIOCGSID;
2183unsigned IOCTL_TIOCCONS = TIOCCONS;
2184unsigned IOCTL_TIOCSCTTY = TIOCSCTTY;
2185unsigned IOCTL_TIOCEXT = TIOCEXT;
2186unsigned IOCTL_TIOCSIG = TIOCSIG;
2187unsigned IOCTL_TIOCDRAIN = TIOCDRAIN;
2188unsigned IOCTL_TIOCGFLAGS = TIOCGFLAGS;
2189unsigned IOCTL_TIOCSFLAGS = TIOCSFLAGS;
2190unsigned IOCTL_TIOCDCDTIMESTAMP = TIOCDCDTIMESTAMP;
2191unsigned IOCTL_TIOCRCVFRAME = TIOCRCVFRAME;
2192unsigned IOCTL_TIOCXMTFRAME = TIOCXMTFRAME;
2193unsigned IOCTL_TIOCPTMGET = TIOCPTMGET;
2194unsigned IOCTL_TIOCGRANTPT = TIOCGRANTPT;
2195unsigned IOCTL_TIOCPTSNAME = TIOCPTSNAME;
2196unsigned IOCTL_TIOCSQSIZE = TIOCSQSIZE;
2197unsigned IOCTL_TIOCGQSIZE = TIOCGQSIZE;
2198unsigned IOCTL_VERIEXEC_LOAD = VERIEXEC_LOAD;
2199unsigned IOCTL_VERIEXEC_TABLESIZE = VERIEXEC_TABLESIZE;
2200unsigned IOCTL_VERIEXEC_DELETE = VERIEXEC_DELETE;
2201unsigned IOCTL_VERIEXEC_QUERY = VERIEXEC_QUERY;
2202unsigned IOCTL_VERIEXEC_DUMP = VERIEXEC_DUMP;
2203unsigned IOCTL_VERIEXEC_FLUSH = VERIEXEC_FLUSH;
2204unsigned IOCTL_VIDIOC_QUERYCAP = VIDIOC_QUERYCAP;
2205unsigned IOCTL_VIDIOC_RESERVED = VIDIOC_RESERVED;
2206unsigned IOCTL_VIDIOC_ENUM_FMT = VIDIOC_ENUM_FMT;
2207unsigned IOCTL_VIDIOC_G_FMT = VIDIOC_G_FMT;
2208unsigned IOCTL_VIDIOC_S_FMT = VIDIOC_S_FMT;
2209unsigned IOCTL_VIDIOC_REQBUFS = VIDIOC_REQBUFS;
2210unsigned IOCTL_VIDIOC_QUERYBUF = VIDIOC_QUERYBUF;
2211unsigned IOCTL_VIDIOC_G_FBUF = VIDIOC_G_FBUF;
2212unsigned IOCTL_VIDIOC_S_FBUF = VIDIOC_S_FBUF;
2213unsigned IOCTL_VIDIOC_OVERLAY = VIDIOC_OVERLAY;
2214unsigned IOCTL_VIDIOC_QBUF = VIDIOC_QBUF;
2215unsigned IOCTL_VIDIOC_DQBUF = VIDIOC_DQBUF;
2216unsigned IOCTL_VIDIOC_STREAMON = VIDIOC_STREAMON;
2217unsigned IOCTL_VIDIOC_STREAMOFF = VIDIOC_STREAMOFF;
2218unsigned IOCTL_VIDIOC_G_PARM = VIDIOC_G_PARM;
2219unsigned IOCTL_VIDIOC_S_PARM = VIDIOC_S_PARM;
2220unsigned IOCTL_VIDIOC_G_STD = VIDIOC_G_STD;
2221unsigned IOCTL_VIDIOC_S_STD = VIDIOC_S_STD;
2222unsigned IOCTL_VIDIOC_ENUMSTD = VIDIOC_ENUMSTD;
2223unsigned IOCTL_VIDIOC_ENUMINPUT = VIDIOC_ENUMINPUT;
2224unsigned IOCTL_VIDIOC_G_CTRL = VIDIOC_G_CTRL;
2225unsigned IOCTL_VIDIOC_S_CTRL = VIDIOC_S_CTRL;
2226unsigned IOCTL_VIDIOC_G_TUNER = VIDIOC_G_TUNER;
2227unsigned IOCTL_VIDIOC_S_TUNER = VIDIOC_S_TUNER;
2228unsigned IOCTL_VIDIOC_G_AUDIO = VIDIOC_G_AUDIO;
2229unsigned IOCTL_VIDIOC_S_AUDIO = VIDIOC_S_AUDIO;
2230unsigned IOCTL_VIDIOC_QUERYCTRL = VIDIOC_QUERYCTRL;
2231unsigned IOCTL_VIDIOC_QUERYMENU = VIDIOC_QUERYMENU;
2232unsigned IOCTL_VIDIOC_G_INPUT = VIDIOC_G_INPUT;
2233unsigned IOCTL_VIDIOC_S_INPUT = VIDIOC_S_INPUT;
2234unsigned IOCTL_VIDIOC_G_OUTPUT = VIDIOC_G_OUTPUT;
2235unsigned IOCTL_VIDIOC_S_OUTPUT = VIDIOC_S_OUTPUT;
2236unsigned IOCTL_VIDIOC_ENUMOUTPUT = VIDIOC_ENUMOUTPUT;
2237unsigned IOCTL_VIDIOC_G_AUDOUT = VIDIOC_G_AUDOUT;
2238unsigned IOCTL_VIDIOC_S_AUDOUT = VIDIOC_S_AUDOUT;
2239unsigned IOCTL_VIDIOC_G_MODULATOR = VIDIOC_G_MODULATOR;
2240unsigned IOCTL_VIDIOC_S_MODULATOR = VIDIOC_S_MODULATOR;
2241unsigned IOCTL_VIDIOC_G_FREQUENCY = VIDIOC_G_FREQUENCY;
2242unsigned IOCTL_VIDIOC_S_FREQUENCY = VIDIOC_S_FREQUENCY;
2243unsigned IOCTL_VIDIOC_CROPCAP = VIDIOC_CROPCAP;
2244unsigned IOCTL_VIDIOC_G_CROP = VIDIOC_G_CROP;
2245unsigned IOCTL_VIDIOC_S_CROP = VIDIOC_S_CROP;
2246unsigned IOCTL_VIDIOC_G_JPEGCOMP = VIDIOC_G_JPEGCOMP;
2247unsigned IOCTL_VIDIOC_S_JPEGCOMP = VIDIOC_S_JPEGCOMP;
2248unsigned IOCTL_VIDIOC_QUERYSTD = VIDIOC_QUERYSTD;
2249unsigned IOCTL_VIDIOC_TRY_FMT = VIDIOC_TRY_FMT;
2250unsigned IOCTL_VIDIOC_ENUMAUDIO = VIDIOC_ENUMAUDIO;
2251unsigned IOCTL_VIDIOC_ENUMAUDOUT = VIDIOC_ENUMAUDOUT;
2252unsigned IOCTL_VIDIOC_G_PRIORITY = VIDIOC_G_PRIORITY;
2253unsigned IOCTL_VIDIOC_S_PRIORITY = VIDIOC_S_PRIORITY;
2254unsigned IOCTL_VIDIOC_ENUM_FRAMESIZES = VIDIOC_ENUM_FRAMESIZES;
2255unsigned IOCTL_VIDIOC_ENUM_FRAMEINTERVALS = VIDIOC_ENUM_FRAMEINTERVALS;
2256unsigned IOCTL_WDOGIOC_GMODE = WDOGIOC_GMODE;
2257unsigned IOCTL_WDOGIOC_SMODE = WDOGIOC_SMODE;
2258unsigned IOCTL_WDOGIOC_WHICH = WDOGIOC_WHICH;
2259unsigned IOCTL_WDOGIOC_TICKLE = WDOGIOC_TICKLE;
2260unsigned IOCTL_WDOGIOC_GTICKLER = WDOGIOC_GTICKLER;
2261unsigned IOCTL_WDOGIOC_GWDOGS = WDOGIOC_GWDOGS;
2262unsigned IOCTL_KCOV_IOC_SETBUFSIZE = KCOV_IOC_SETBUFSIZE;
2263unsigned IOCTL_KCOV_IOC_ENABLE = KCOV_IOC_ENABLE;
2264unsigned IOCTL_KCOV_IOC_DISABLE = KCOV_IOC_DISABLE;
2265unsigned IOCTL_IPMICTL_RECEIVE_MSG_TRUNC = IPMICTL_RECEIVE_MSG_TRUNC;
2266unsigned IOCTL_IPMICTL_RECEIVE_MSG = IPMICTL_RECEIVE_MSG;
2267unsigned IOCTL_IPMICTL_SEND_COMMAND = IPMICTL_SEND_COMMAND;
2268unsigned IOCTL_IPMICTL_REGISTER_FOR_CMD = IPMICTL_REGISTER_FOR_CMD;
2269unsigned IOCTL_IPMICTL_UNREGISTER_FOR_CMD = IPMICTL_UNREGISTER_FOR_CMD;
2270unsigned IOCTL_IPMICTL_SET_GETS_EVENTS_CMD = IPMICTL_SET_GETS_EVENTS_CMD;
2271unsigned IOCTL_IPMICTL_SET_MY_ADDRESS_CMD = IPMICTL_SET_MY_ADDRESS_CMD;
2272unsigned IOCTL_IPMICTL_GET_MY_ADDRESS_CMD = IPMICTL_GET_MY_ADDRESS_CMD;
2273unsigned IOCTL_IPMICTL_SET_MY_LUN_CMD = IPMICTL_SET_MY_LUN_CMD;
2274unsigned IOCTL_IPMICTL_GET_MY_LUN_CMD = IPMICTL_GET_MY_LUN_CMD;
2275unsigned IOCTL_SNDCTL_DSP_RESET = SNDCTL_DSP_RESET;
2276unsigned IOCTL_SNDCTL_DSP_SYNC = SNDCTL_DSP_SYNC;
2277unsigned IOCTL_SNDCTL_DSP_SPEED = SNDCTL_DSP_SPEED;
2278unsigned IOCTL_SOUND_PCM_READ_RATE = SOUND_PCM_READ_RATE;
2279unsigned IOCTL_SNDCTL_DSP_STEREO = SNDCTL_DSP_STEREO;
2280unsigned IOCTL_SNDCTL_DSP_GETBLKSIZE = SNDCTL_DSP_GETBLKSIZE;
2281unsigned IOCTL_SNDCTL_DSP_SETFMT = SNDCTL_DSP_SETFMT;
2282unsigned IOCTL_SOUND_PCM_READ_BITS = SOUND_PCM_READ_BITS;
2283unsigned IOCTL_SNDCTL_DSP_CHANNELS = SNDCTL_DSP_CHANNELS;
2284unsigned IOCTL_SOUND_PCM_READ_CHANNELS = SOUND_PCM_READ_CHANNELS;
2285unsigned IOCTL_SOUND_PCM_WRITE_FILTER = SOUND_PCM_WRITE_FILTER;
2286unsigned IOCTL_SOUND_PCM_READ_FILTER = SOUND_PCM_READ_FILTER;
2287unsigned IOCTL_SNDCTL_DSP_POST = SNDCTL_DSP_POST;
2288unsigned IOCTL_SNDCTL_DSP_SUBDIVIDE = SNDCTL_DSP_SUBDIVIDE;
2289unsigned IOCTL_SNDCTL_DSP_SETFRAGMENT = SNDCTL_DSP_SETFRAGMENT;
2290unsigned IOCTL_SNDCTL_DSP_GETFMTS = SNDCTL_DSP_GETFMTS;
2291unsigned IOCTL_SNDCTL_DSP_GETOSPACE = SNDCTL_DSP_GETOSPACE;
2292unsigned IOCTL_SNDCTL_DSP_GETISPACE = SNDCTL_DSP_GETISPACE;
2293unsigned IOCTL_SNDCTL_DSP_NONBLOCK = SNDCTL_DSP_NONBLOCK;
2294unsigned IOCTL_SNDCTL_DSP_GETCAPS = SNDCTL_DSP_GETCAPS;
2295unsigned IOCTL_SNDCTL_DSP_GETTRIGGER = SNDCTL_DSP_GETTRIGGER;
2296unsigned IOCTL_SNDCTL_DSP_SETTRIGGER = SNDCTL_DSP_SETTRIGGER;
2297unsigned IOCTL_SNDCTL_DSP_GETIPTR = SNDCTL_DSP_GETIPTR;
2298unsigned IOCTL_SNDCTL_DSP_GETOPTR = SNDCTL_DSP_GETOPTR;
2299unsigned IOCTL_SNDCTL_DSP_MAPINBUF = SNDCTL_DSP_MAPINBUF;
2300unsigned IOCTL_SNDCTL_DSP_MAPOUTBUF = SNDCTL_DSP_MAPOUTBUF;
2301unsigned IOCTL_SNDCTL_DSP_SETSYNCRO = SNDCTL_DSP_SETSYNCRO;
2302unsigned IOCTL_SNDCTL_DSP_SETDUPLEX = SNDCTL_DSP_SETDUPLEX;
2303unsigned IOCTL_SNDCTL_DSP_PROFILE = SNDCTL_DSP_PROFILE;
2304unsigned IOCTL_SNDCTL_DSP_GETODELAY = SNDCTL_DSP_GETODELAY;
2305unsigned IOCTL_SOUND_MIXER_INFO = SOUND_MIXER_INFO;
2306unsigned IOCTL_SOUND_OLD_MIXER_INFO = SOUND_OLD_MIXER_INFO;
2307unsigned IOCTL_OSS_GETVERSION = OSS_GETVERSION;
2308unsigned IOCTL_SNDCTL_SYSINFO = SNDCTL_SYSINFO;
2309unsigned IOCTL_SNDCTL_AUDIOINFO = SNDCTL_AUDIOINFO;
2310unsigned IOCTL_SNDCTL_ENGINEINFO = SNDCTL_ENGINEINFO;
2311unsigned IOCTL_SNDCTL_DSP_GETPLAYVOL = SNDCTL_DSP_GETPLAYVOL;
2312unsigned IOCTL_SNDCTL_DSP_SETPLAYVOL = SNDCTL_DSP_SETPLAYVOL;
2313unsigned IOCTL_SNDCTL_DSP_GETRECVOL = SNDCTL_DSP_GETRECVOL;
2314unsigned IOCTL_SNDCTL_DSP_SETRECVOL = SNDCTL_DSP_SETRECVOL;
2315unsigned IOCTL_SNDCTL_DSP_SKIP = SNDCTL_DSP_SKIP;
2316unsigned IOCTL_SNDCTL_DSP_SILENCE = SNDCTL_DSP_SILENCE;
2317
2318const int si_SEGV_MAPERR = SEGV_MAPERR;
2319const int si_SEGV_ACCERR = SEGV_ACCERR;
2320
2321const int modctl_load = MODCTL_LOAD;
2322const int modctl_unload = MODCTL_UNLOAD;
2323const int modctl_stat = MODCTL_STAT;
2324const int modctl_exists = MODCTL_EXISTS;
2325
2326const unsigned SHA1_CTX_sz = sizeof(SHA1_CTX);
2327const unsigned SHA1_return_length = SHA1_DIGEST_STRING_LENGTH;
2328
2329const unsigned MD4_CTX_sz = sizeof(MD4_CTX);
2330const unsigned MD4_return_length = MD4_DIGEST_STRING_LENGTH;
2331
2332const unsigned RMD160_CTX_sz = sizeof(RMD160_CTX);
2333const unsigned RMD160_return_length = RMD160_DIGEST_STRING_LENGTH;
2334
2335const unsigned MD5_CTX_sz = sizeof(MD5_CTX);
2336const unsigned MD5_return_length = MD5_DIGEST_STRING_LENGTH;
2337
2338const unsigned fpos_t_sz = sizeof(fpos_t);
2339
2340const unsigned MD2_CTX_sz = sizeof(MD2_CTX);
2341const unsigned MD2_return_length = MD2_DIGEST_STRING_LENGTH;
2342
2343#define SHA2_CONST(LEN) \
2344 const unsigned SHA##LEN##_CTX_sz = sizeof(SHA##LEN##_CTX); \
2345 const unsigned SHA##LEN##_return_length = SHA##LEN##_DIGEST_STRING_LENGTH; \
2346 const unsigned SHA##LEN##_block_length = SHA##LEN##_BLOCK_LENGTH; \
2347 const unsigned SHA##LEN##_digest_length = SHA##LEN##_DIGEST_LENGTH
2348
2349SHA2_CONST(224);
2350SHA2_CONST(256);
2351SHA2_CONST(384);
2352SHA2_CONST(512);
2353
2354#undef SHA2_CONST
2355
2356const int unvis_valid = UNVIS_VALID;
2357const int unvis_validpush = UNVIS_VALIDPUSH;
2358} // namespace __sanitizer
2359
2360using namespace __sanitizer;
2361
2362COMPILER_CHECK(sizeof(__sanitizer_pthread_attr_t) >= sizeof(pthread_attr_t));
2363
2364COMPILER_CHECK(sizeof(socklen_t) == sizeof(unsigned));
2365CHECK_TYPE_SIZE(pthread_key_t);
2366
2367// There are more undocumented fields in dl_phdr_info that we are not interested
2368// in.
2369COMPILER_CHECK(sizeof(__sanitizer_dl_phdr_info) <= sizeof(dl_phdr_info));
2370CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_addr);
2371CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_name);
2372CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_phdr);
2373CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_phnum);
2374
2375CHECK_TYPE_SIZE(glob_t);
2376CHECK_SIZE_AND_OFFSET(glob_t, gl_pathc);
2377CHECK_SIZE_AND_OFFSET(glob_t, gl_pathv);
2378CHECK_SIZE_AND_OFFSET(glob_t, gl_offs);
2379CHECK_SIZE_AND_OFFSET(glob_t, gl_flags);
2380CHECK_SIZE_AND_OFFSET(glob_t, gl_closedir);
2381CHECK_SIZE_AND_OFFSET(glob_t, gl_readdir);
2382CHECK_SIZE_AND_OFFSET(glob_t, gl_opendir);
2383CHECK_SIZE_AND_OFFSET(glob_t, gl_lstat);
2384CHECK_SIZE_AND_OFFSET(glob_t, gl_stat);
2385
2386CHECK_TYPE_SIZE(addrinfo);
2387CHECK_SIZE_AND_OFFSET(addrinfo, ai_flags);
2388CHECK_SIZE_AND_OFFSET(addrinfo, ai_family);
2389CHECK_SIZE_AND_OFFSET(addrinfo, ai_socktype);
2390CHECK_SIZE_AND_OFFSET(addrinfo, ai_protocol);
2391CHECK_SIZE_AND_OFFSET(addrinfo, ai_protocol);
2392CHECK_SIZE_AND_OFFSET(addrinfo, ai_addrlen);
2393CHECK_SIZE_AND_OFFSET(addrinfo, ai_canonname);
2394CHECK_SIZE_AND_OFFSET(addrinfo, ai_addr);
2395
2396CHECK_TYPE_SIZE(hostent);
2397CHECK_SIZE_AND_OFFSET(hostent, h_name);
2398CHECK_SIZE_AND_OFFSET(hostent, h_aliases);
2399CHECK_SIZE_AND_OFFSET(hostent, h_addrtype);
2400CHECK_SIZE_AND_OFFSET(hostent, h_length);
2401CHECK_SIZE_AND_OFFSET(hostent, h_addr_list);
2402
2403CHECK_TYPE_SIZE(iovec);
2404CHECK_SIZE_AND_OFFSET(iovec, iov_base);
2405CHECK_SIZE_AND_OFFSET(iovec, iov_len);
2406
2407CHECK_TYPE_SIZE(msghdr);
2408CHECK_SIZE_AND_OFFSET(msghdr, msg_name);
2409CHECK_SIZE_AND_OFFSET(msghdr, msg_namelen);
2410CHECK_SIZE_AND_OFFSET(msghdr, msg_iov);
2411CHECK_SIZE_AND_OFFSET(msghdr, msg_iovlen);
2412CHECK_SIZE_AND_OFFSET(msghdr, msg_control);
2413CHECK_SIZE_AND_OFFSET(msghdr, msg_controllen);
2414CHECK_SIZE_AND_OFFSET(msghdr, msg_flags);
2415
2416CHECK_TYPE_SIZE(cmsghdr);
2417CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_len);
2418CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_level);
2419CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_type);
2420
2421COMPILER_CHECK(sizeof(__sanitizer_dirent) <= sizeof(dirent));
2422CHECK_SIZE_AND_OFFSET(dirent, d_fileno);
2423CHECK_SIZE_AND_OFFSET(dirent, d_reclen);
2424
2425CHECK_TYPE_SIZE(ifconf);
2426CHECK_SIZE_AND_OFFSET(ifconf, ifc_len);
2427CHECK_SIZE_AND_OFFSET(ifconf, ifc_ifcu);
2428
2429CHECK_TYPE_SIZE(pollfd);
2430CHECK_SIZE_AND_OFFSET(pollfd, fd);
2431CHECK_SIZE_AND_OFFSET(pollfd, events);
2432CHECK_SIZE_AND_OFFSET(pollfd, revents);
2433
2434CHECK_TYPE_SIZE(nfds_t);
2435
2436CHECK_TYPE_SIZE(sigset_t);
2437
2438COMPILER_CHECK(sizeof(__sanitizer_sigaction) == sizeof(struct sigaction));
2439// Can't write checks for sa_handler and sa_sigaction due to them being
2440// preprocessor macros.
2441CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_mask);
2442
2443CHECK_TYPE_SIZE(wordexp_t);
2444CHECK_SIZE_AND_OFFSET(wordexp_t, we_wordc);
2445CHECK_SIZE_AND_OFFSET(wordexp_t, we_wordv);
2446CHECK_SIZE_AND_OFFSET(wordexp_t, we_offs);
2447
2448COMPILER_CHECK(sizeof(__sanitizer_FILE) <= sizeof(FILE));
2449CHECK_SIZE_AND_OFFSET(FILE, _p);
2450CHECK_SIZE_AND_OFFSET(FILE, _r);
2451CHECK_SIZE_AND_OFFSET(FILE, _w);
2452CHECK_SIZE_AND_OFFSET(FILE, _flags);
2453CHECK_SIZE_AND_OFFSET(FILE, _file);
2454CHECK_SIZE_AND_OFFSET(FILE, _bf);
2455CHECK_SIZE_AND_OFFSET(FILE, _lbfsize);
2456CHECK_SIZE_AND_OFFSET(FILE, _cookie);
2457CHECK_SIZE_AND_OFFSET(FILE, _close);
2458CHECK_SIZE_AND_OFFSET(FILE, _read);
2459CHECK_SIZE_AND_OFFSET(FILE, _seek);
2460CHECK_SIZE_AND_OFFSET(FILE, _write);
2461CHECK_SIZE_AND_OFFSET(FILE, _ext);
2462CHECK_SIZE_AND_OFFSET(FILE, _up);
2463CHECK_SIZE_AND_OFFSET(FILE, _ur);
2464CHECK_SIZE_AND_OFFSET(FILE, _ubuf);
2465CHECK_SIZE_AND_OFFSET(FILE, _nbuf);
2466CHECK_SIZE_AND_OFFSET(FILE, _flush);
2467CHECK_SIZE_AND_OFFSET(FILE, _lb_unused);
2468CHECK_SIZE_AND_OFFSET(FILE, _blksize);
2469CHECK_SIZE_AND_OFFSET(FILE, _offset);
2470
2471CHECK_TYPE_SIZE(tm);
2472CHECK_SIZE_AND_OFFSET(tm, tm_sec);
2473CHECK_SIZE_AND_OFFSET(tm, tm_min);
2474CHECK_SIZE_AND_OFFSET(tm, tm_hour);
2475CHECK_SIZE_AND_OFFSET(tm, tm_mday);
2476CHECK_SIZE_AND_OFFSET(tm, tm_mon);
2477CHECK_SIZE_AND_OFFSET(tm, tm_year);
2478CHECK_SIZE_AND_OFFSET(tm, tm_wday);
2479CHECK_SIZE_AND_OFFSET(tm, tm_yday);
2480CHECK_SIZE_AND_OFFSET(tm, tm_isdst);
2481CHECK_SIZE_AND_OFFSET(tm, tm_gmtoff);
2482CHECK_SIZE_AND_OFFSET(tm, tm_zone);
2483
2484CHECK_TYPE_SIZE(ether_addr);
2485
2486CHECK_TYPE_SIZE(ipc_perm);
2487CHECK_SIZE_AND_OFFSET(ipc_perm, _key);
2488CHECK_SIZE_AND_OFFSET(ipc_perm, _seq);
2489CHECK_SIZE_AND_OFFSET(ipc_perm, uid);
2490CHECK_SIZE_AND_OFFSET(ipc_perm, gid);
2491CHECK_SIZE_AND_OFFSET(ipc_perm, cuid);
2492CHECK_SIZE_AND_OFFSET(ipc_perm, cgid);
2493CHECK_SIZE_AND_OFFSET(ipc_perm, mode);
2494
2495CHECK_TYPE_SIZE(shmid_ds);
2496CHECK_SIZE_AND_OFFSET(shmid_ds, shm_perm);
2497CHECK_SIZE_AND_OFFSET(shmid_ds, shm_segsz);
2498CHECK_SIZE_AND_OFFSET(shmid_ds, shm_atime);
2499CHECK_SIZE_AND_OFFSET(shmid_ds, shm_dtime);
2500CHECK_SIZE_AND_OFFSET(shmid_ds, shm_ctime);
2501CHECK_SIZE_AND_OFFSET(shmid_ds, shm_cpid);
2502CHECK_SIZE_AND_OFFSET(shmid_ds, shm_lpid);
2503CHECK_SIZE_AND_OFFSET(shmid_ds, shm_nattch);
2504
2505CHECK_TYPE_SIZE(clock_t);
2506
2507CHECK_TYPE_SIZE(ifaddrs);
2508CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_next);
2509CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_name);
2510CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_addr);
2511CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_netmask);
2512// Compare against the union, because we can't reach into the union in a
2513// compliant way.
2514#ifdef ifa_dstaddr
2515#undef ifa_dstaddr
2516#endif
2517CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_dstaddr);
2518CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_data);
2519
2520CHECK_TYPE_SIZE(timeb);
2521CHECK_SIZE_AND_OFFSET(timeb, time);
2522CHECK_SIZE_AND_OFFSET(timeb, millitm);
2523CHECK_SIZE_AND_OFFSET(timeb, timezone);
2524CHECK_SIZE_AND_OFFSET(timeb, dstflag);
2525
2526CHECK_TYPE_SIZE(passwd);
2527CHECK_SIZE_AND_OFFSET(passwd, pw_name);
2528CHECK_SIZE_AND_OFFSET(passwd, pw_passwd);
2529CHECK_SIZE_AND_OFFSET(passwd, pw_uid);
2530CHECK_SIZE_AND_OFFSET(passwd, pw_gid);
2531CHECK_SIZE_AND_OFFSET(passwd, pw_dir);
2532CHECK_SIZE_AND_OFFSET(passwd, pw_shell);
2533
2534CHECK_SIZE_AND_OFFSET(passwd, pw_gecos);
2535
2536CHECK_TYPE_SIZE(group);
2537CHECK_SIZE_AND_OFFSET(group, gr_name);
2538CHECK_SIZE_AND_OFFSET(group, gr_passwd);
2539CHECK_SIZE_AND_OFFSET(group, gr_gid);
2540CHECK_SIZE_AND_OFFSET(group, gr_mem);
2541
2542CHECK_TYPE_SIZE(modctl_load_t);
2543CHECK_SIZE_AND_OFFSET(modctl_load_t, ml_filename);
2544CHECK_SIZE_AND_OFFSET(modctl_load_t, ml_flags);
2545CHECK_SIZE_AND_OFFSET(modctl_load_t, ml_props);
2546CHECK_SIZE_AND_OFFSET(modctl_load_t, ml_propslen);
2547
2548// Compat with 9.0
2549struct statvfs90 {
2550 unsigned long f_flag;
2551 unsigned long f_bsize;
2552 unsigned long f_frsize;
2553 unsigned long f_iosize;
2554
2555 u64 f_blocks;
2556 u64 f_bfree;
2557 u64 f_bavail;
2558 u64 f_bresvd;
2559
2560 u64 f_files;
2561 u64 f_ffree;
2562 u64 f_favail;
2563 u64 f_fresvd;
2564
2565 u64 f_syncreads;
2566 u64 f_syncwrites;
2567
2568 u64 f_asyncreads;
2569 u64 f_asyncwrites;
2570
2571 struct {
2572 s32 __fsid_val[2];
2573 } f_fsidx;
2574 unsigned long f_fsid;
2575 unsigned long f_namemax;
2576 u32 f_owner;
2577
2578 u32 f_spare[4];
2579
2580 char f_fstypename[32];
2581 char f_mntonname[32];
2582 char f_mntfromname[32];
2583};
2584unsigned struct_statvfs90_sz = sizeof(struct statvfs90);
2585
2586#endif // SANITIZER_NETBSD
lib/tsan/sanitizer_common/sanitizer_platform_limits_netbsd.h created+2422
...@@ -0,0 +1,2422 @@
1//===-- sanitizer_platform_limits_netbsd.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// Sizes and layouts of platform-specific NetBSD data structures.
12//===----------------------------------------------------------------------===//
13
14#ifndef SANITIZER_PLATFORM_LIMITS_NETBSD_H
15#define SANITIZER_PLATFORM_LIMITS_NETBSD_H
16
17#if SANITIZER_NETBSD
18
19#include "sanitizer_internal_defs.h"
20#include "sanitizer_platform.h"
21
22namespace __sanitizer {
23void *__sanitizer_get_link_map_by_dlopen_handle(void *handle);
24# define GET_LINK_MAP_BY_DLOPEN_HANDLE(handle) \
25 (link_map *)__sanitizer_get_link_map_by_dlopen_handle(handle)
26
27extern unsigned struct_utsname_sz;
28extern unsigned struct_stat_sz;
29extern unsigned struct_rusage_sz;
30extern unsigned siginfo_t_sz;
31extern unsigned struct_itimerval_sz;
32extern unsigned pthread_t_sz;
33extern unsigned pthread_mutex_t_sz;
34extern unsigned pthread_cond_t_sz;
35extern unsigned pid_t_sz;
36extern unsigned timeval_sz;
37extern unsigned uid_t_sz;
38extern unsigned gid_t_sz;
39extern unsigned mbstate_t_sz;
40extern unsigned struct_timezone_sz;
41extern unsigned struct_tms_sz;
42extern unsigned struct_itimerspec_sz;
43extern unsigned struct_sigevent_sz;
44extern unsigned struct_stack_t_sz;
45extern unsigned struct_sched_param_sz;
46extern unsigned struct_statfs_sz;
47extern unsigned struct_sockaddr_sz;
48extern unsigned ucontext_t_sz;
49
50extern unsigned struct_rlimit_sz;
51extern unsigned struct_utimbuf_sz;
52extern unsigned struct_timespec_sz;
53extern unsigned struct_sembuf_sz;
54
55extern unsigned struct_kevent_sz;
56extern unsigned struct_FTS_sz;
57extern unsigned struct_FTSENT_sz;
58
59extern unsigned struct_regex_sz;
60extern unsigned struct_regmatch_sz;
61
62extern unsigned struct_fstab_sz;
63
64struct __sanitizer_regmatch {
65 OFF_T rm_so;
66 OFF_T rm_eo;
67};
68
69typedef struct __sanitizer_modctl_load {
70 const char *ml_filename;
71 int ml_flags;
72 const char *ml_props;
73 uptr ml_propslen;
74} __sanitizer_modctl_load_t;
75extern const int modctl_load;
76extern const int modctl_unload;
77extern const int modctl_stat;
78extern const int modctl_exists;
79
80union __sanitizer_sigval {
81 int sival_int;
82 uptr sival_ptr;
83};
84
85struct __sanitizer_sigevent {
86 int sigev_notify;
87 int sigev_signo;
88 union __sanitizer_sigval sigev_value;
89 uptr sigev_notify_function;
90 uptr sigev_notify_attributes;
91};
92
93struct __sanitizer_aiocb {
94 u64 aio_offset;
95 uptr aio_buf;
96 uptr aio_nbytes;
97 int aio_fildes;
98 int aio_lio_opcode;
99 int aio_reqprio;
100 struct __sanitizer_sigevent aio_sigevent;
101 int _state;
102 int _errno;
103 long _retval;
104};
105
106struct __sanitizer_sem_t {
107 uptr data[5];
108};
109
110struct __sanitizer_ipc_perm {
111 u32 uid;
112 u32 gid;
113 u32 cuid;
114 u32 cgid;
115 u32 mode;
116 unsigned short _seq;
117 long _key;
118};
119
120struct __sanitizer_shmid_ds {
121 __sanitizer_ipc_perm shm_perm;
122 unsigned long shm_segsz;
123 u32 shm_lpid;
124 u32 shm_cpid;
125 unsigned int shm_nattch;
126 u64 shm_atime;
127 u64 shm_dtime;
128 u64 shm_ctime;
129 void *_shm_internal;
130};
131
132struct __sanitizer_protoent {
133 char *p_name;
134 char **p_aliases;
135 int p_proto;
136};
137
138struct __sanitizer_netent {
139 char *n_name;
140 char **n_aliases;
141 int n_addrtype;
142 u32 n_net;
143};
144
145extern unsigned struct_msqid_ds_sz;
146extern unsigned struct_mq_attr_sz;
147extern unsigned struct_timex_sz;
148extern unsigned struct_statvfs_sz;
149
150struct __sanitizer_iovec {
151 void *iov_base;
152 uptr iov_len;
153};
154
155struct __sanitizer_ifaddrs {
156 struct __sanitizer_ifaddrs *ifa_next;
157 char *ifa_name;
158 unsigned int ifa_flags;
159 void *ifa_addr; // (struct sockaddr *)
160 void *ifa_netmask; // (struct sockaddr *)
161 void *ifa_dstaddr; // (struct sockaddr *)
162 void *ifa_data;
163 unsigned int ifa_addrflags;
164};
165
166typedef unsigned int __sanitizer_socklen_t;
167
168typedef unsigned __sanitizer_pthread_key_t;
169
170typedef long long __sanitizer_time_t;
171typedef int __sanitizer_suseconds_t;
172
173struct __sanitizer_timeval {
174 __sanitizer_time_t tv_sec;
175 __sanitizer_suseconds_t tv_usec;
176};
177
178struct __sanitizer_itimerval {
179 struct __sanitizer_timeval it_interval;
180 struct __sanitizer_timeval it_value;
181};
182
183struct __sanitizer_timespec {
184 __sanitizer_time_t tv_sec;
185 long tv_nsec;
186};
187
188struct __sanitizer_passwd {
189 char *pw_name;
190 char *pw_passwd;
191 int pw_uid;
192 int pw_gid;
193 __sanitizer_time_t pw_change;
194 char *pw_class;
195 char *pw_gecos;
196 char *pw_dir;
197 char *pw_shell;
198 __sanitizer_time_t pw_expire;
199};
200
201struct __sanitizer_group {
202 char *gr_name;
203 char *gr_passwd;
204 int gr_gid;
205 char **gr_mem;
206};
207
208struct __sanitizer_timeb {
209 __sanitizer_time_t time;
210 unsigned short millitm;
211 short timezone;
212 short dstflag;
213};
214
215struct __sanitizer_ether_addr {
216 u8 octet[6];
217};
218
219struct __sanitizer_tm {
220 int tm_sec;
221 int tm_min;
222 int tm_hour;
223 int tm_mday;
224 int tm_mon;
225 int tm_year;
226 int tm_wday;
227 int tm_yday;
228 int tm_isdst;
229 long int tm_gmtoff;
230 const char *tm_zone;
231};
232
233struct __sanitizer_msghdr {
234 void *msg_name;
235 unsigned msg_namelen;
236 struct __sanitizer_iovec *msg_iov;
237 unsigned msg_iovlen;
238 void *msg_control;
239 unsigned msg_controllen;
240 int msg_flags;
241};
242
243struct __sanitizer_mmsghdr {
244 struct __sanitizer_msghdr msg_hdr;
245 unsigned int msg_len;
246};
247
248struct __sanitizer_cmsghdr {
249 unsigned cmsg_len;
250 int cmsg_level;
251 int cmsg_type;
252};
253
254struct __sanitizer_dirent {
255 u64 d_fileno;
256 u16 d_reclen;
257 // more fields that we don't care about
258};
259
260typedef int __sanitizer_clock_t;
261typedef int __sanitizer_clockid_t;
262
263typedef u32 __sanitizer___kernel_uid_t;
264typedef u32 __sanitizer___kernel_gid_t;
265typedef u64 __sanitizer___kernel_off_t;
266typedef struct {
267 u32 fds_bits[8];
268} __sanitizer___kernel_fd_set;
269
270typedef struct {
271 unsigned int pta_magic;
272 int pta_flags;
273 void *pta_private;
274} __sanitizer_pthread_attr_t;
275
276struct __sanitizer_sigset_t {
277 // uint32_t * 4
278 unsigned int __bits[4];
279};
280
281struct __sanitizer_siginfo {
282 // The size is determined by looking at sizeof of real siginfo_t on linux.
283 u64 opaque[128 / sizeof(u64)];
284};
285
286using __sanitizer_sighandler_ptr = void (*)(int sig);
287using __sanitizer_sigactionhandler_ptr = void (*)(int sig,
288 __sanitizer_siginfo *siginfo,
289 void *uctx);
290
291struct __sanitizer_sigaction {
292 union {
293 __sanitizer_sighandler_ptr handler;
294 __sanitizer_sigactionhandler_ptr sigaction;
295 };
296 __sanitizer_sigset_t sa_mask;
297 int sa_flags;
298};
299
300extern unsigned struct_sigaltstack_sz;
301
302typedef unsigned int __sanitizer_sigset13_t;
303
304struct __sanitizer_sigaction13 {
305 __sanitizer_sighandler_ptr osa_handler;
306 __sanitizer_sigset13_t osa_mask;
307 int osa_flags;
308};
309
310struct __sanitizer_sigaltstack {
311 void *ss_sp;
312 uptr ss_size;
313 int ss_flags;
314};
315
316typedef __sanitizer_sigset_t __sanitizer_kernel_sigset_t;
317
318struct __sanitizer_kernel_sigaction_t {
319 union {
320 void (*handler)(int signo);
321 void (*sigaction)(int signo, void *info, void *ctx);
322 };
323 unsigned long sa_flags;
324 void (*sa_restorer)(void);
325 __sanitizer_kernel_sigset_t sa_mask;
326};
327
328extern const uptr sig_ign;
329extern const uptr sig_dfl;
330extern const uptr sig_err;
331extern const uptr sa_siginfo;
332
333extern int af_inet;
334extern int af_inet6;
335uptr __sanitizer_in_addr_sz(int af);
336
337struct __sanitizer_dl_phdr_info {
338 uptr dlpi_addr;
339 const char *dlpi_name;
340 const void *dlpi_phdr;
341 short dlpi_phnum;
342};
343
344extern unsigned struct_ElfW_Phdr_sz;
345
346struct __sanitizer_addrinfo {
347 int ai_flags;
348 int ai_family;
349 int ai_socktype;
350 int ai_protocol;
351#if defined(__sparc__) && defined(_LP64)
352 int __ai_pad0;
353#endif
354 unsigned ai_addrlen;
355#if defined(__alpha__) || (defined(__i386__) && defined(_LP64))
356 int __ai_pad0;
357#endif
358 char *ai_canonname;
359 void *ai_addr;
360 struct __sanitizer_addrinfo *ai_next;
361};
362
363struct __sanitizer_hostent {
364 char *h_name;
365 char **h_aliases;
366 int h_addrtype;
367 int h_length;
368 char **h_addr_list;
369};
370
371struct __sanitizer_pollfd {
372 int fd;
373 short events;
374 short revents;
375};
376
377typedef unsigned __sanitizer_nfds_t;
378
379typedef int __sanitizer_lwpid_t;
380
381struct __sanitizer_glob_t {
382 uptr gl_pathc;
383 uptr gl_matchc;
384 uptr gl_offs;
385 int gl_flags;
386 char **gl_pathv;
387 int (*gl_errfunc)(const char *, int);
388 void (*gl_closedir)(void *dirp);
389 struct dirent *(*gl_readdir)(void *dirp);
390 void *(*gl_opendir)(const char *);
391 int (*gl_lstat)(const char *, void * /* struct stat* */);
392 int (*gl_stat)(const char *, void * /* struct stat* */);
393};
394
395extern int glob_nomatch;
396extern int glob_altdirfunc;
397
398extern unsigned path_max;
399
400extern int struct_ttyent_sz;
401
402extern int ptrace_pt_io;
403extern int ptrace_pt_lwpinfo;
404extern int ptrace_pt_set_event_mask;
405extern int ptrace_pt_get_event_mask;
406extern int ptrace_pt_get_process_state;
407extern int ptrace_pt_set_siginfo;
408extern int ptrace_pt_get_siginfo;
409extern int ptrace_pt_lwpstatus;
410extern int ptrace_pt_lwpnext;
411extern int ptrace_piod_read_d;
412extern int ptrace_piod_write_d;
413extern int ptrace_piod_read_i;
414extern int ptrace_piod_write_i;
415extern int ptrace_piod_read_auxv;
416extern int ptrace_pt_setregs;
417extern int ptrace_pt_getregs;
418extern int ptrace_pt_setfpregs;
419extern int ptrace_pt_getfpregs;
420extern int ptrace_pt_setdbregs;
421extern int ptrace_pt_getdbregs;
422
423struct __sanitizer_ptrace_io_desc {
424 int piod_op;
425 void *piod_offs;
426 void *piod_addr;
427 uptr piod_len;
428};
429
430struct __sanitizer_ptrace_lwpinfo {
431 __sanitizer_lwpid_t pl_lwpid;
432 int pl_event;
433};
434
435struct __sanitizer_ptrace_lwpstatus {
436 __sanitizer_lwpid_t pl_lwpid;
437 __sanitizer_sigset_t pl_sigpend;
438 __sanitizer_sigset_t pl_sigmask;
439 char pl_name[20];
440 void *pl_private;
441};
442
443extern unsigned struct_ptrace_ptrace_io_desc_struct_sz;
444extern unsigned struct_ptrace_ptrace_lwpinfo_struct_sz;
445extern unsigned struct_ptrace_ptrace_lwpstatus_struct_sz;
446extern unsigned struct_ptrace_ptrace_event_struct_sz;
447extern unsigned struct_ptrace_ptrace_siginfo_struct_sz;
448
449extern unsigned struct_ptrace_reg_struct_sz;
450extern unsigned struct_ptrace_fpreg_struct_sz;
451extern unsigned struct_ptrace_dbreg_struct_sz;
452
453struct __sanitizer_wordexp_t {
454 uptr we_wordc;
455 char **we_wordv;
456 uptr we_offs;
457 char *we_strings;
458 uptr we_nbytes;
459};
460
461struct __sanitizer_FILE {
462 unsigned char *_p;
463 int _r;
464 int _w;
465 unsigned short _flags;
466 short _file;
467 struct {
468 unsigned char *_base;
469 int _size;
470 } _bf;
471 int _lbfsize;
472 void *_cookie;
473 int (*_close)(void *ptr);
474 u64 (*_read)(void *, void *, uptr);
475 u64 (*_seek)(void *, u64, int);
476 uptr (*_write)(void *, const void *, uptr);
477 struct {
478 unsigned char *_base;
479 int _size;
480 } _ext;
481 unsigned char *_up;
482 int _ur;
483 unsigned char _ubuf[3];
484 unsigned char _nbuf[1];
485 int (*_flush)(void *ptr);
486 char _lb_unused[sizeof(uptr)];
487 int _blksize;
488 u64 _offset;
489};
490#define SANITIZER_HAS_STRUCT_FILE 1
491
492extern int shmctl_ipc_stat;
493
494// This simplifies generic code
495#define struct_shminfo_sz -1
496#define struct_shm_info_sz -1
497#define shmctl_shm_stat -1
498#define shmctl_ipc_info -1
499#define shmctl_shm_info -1
500
501extern unsigned struct_utmp_sz;
502extern unsigned struct_utmpx_sz;
503
504extern int map_fixed;
505
506// ioctl arguments
507struct __sanitizer_ifconf {
508 int ifc_len;
509 union {
510 void *ifcu_req;
511 } ifc_ifcu;
512};
513
514struct __sanitizer_ttyent {
515 char *ty_name;
516 char *ty_getty;
517 char *ty_type;
518 int ty_status;
519 char *ty_window;
520 char *ty_comment;
521 char *ty_class;
522};
523
524extern const unsigned long __sanitizer_bufsiz;
525
526#define IOC_NRBITS 8
527#define IOC_TYPEBITS 8
528#define IOC_SIZEBITS 14
529#define IOC_DIRBITS 2
530#define IOC_NONE 0U
531#define IOC_WRITE 1U
532#define IOC_READ 2U
533#define IOC_NRMASK ((1 << IOC_NRBITS) - 1)
534#define IOC_TYPEMASK ((1 << IOC_TYPEBITS) - 1)
535#define IOC_SIZEMASK ((1 << IOC_SIZEBITS) - 1)
536#undef IOC_DIRMASK
537#define IOC_DIRMASK ((1 << IOC_DIRBITS) - 1)
538#define IOC_NRSHIFT 0
539#define IOC_TYPESHIFT (IOC_NRSHIFT + IOC_NRBITS)
540#define IOC_SIZESHIFT (IOC_TYPESHIFT + IOC_TYPEBITS)
541#define IOC_DIRSHIFT (IOC_SIZESHIFT + IOC_SIZEBITS)
542#define EVIOC_EV_MAX 0x1f
543#define EVIOC_ABS_MAX 0x3f
544
545#define IOC_DIR(nr) (((nr) >> IOC_DIRSHIFT) & IOC_DIRMASK)
546#define IOC_TYPE(nr) (((nr) >> IOC_TYPESHIFT) & IOC_TYPEMASK)
547#define IOC_NR(nr) (((nr) >> IOC_NRSHIFT) & IOC_NRMASK)
548#define IOC_SIZE(nr) (((nr) >> IOC_SIZESHIFT) & IOC_SIZEMASK)
549
550// ioctl request identifiers
551
552extern unsigned struct_altqreq_sz;
553extern unsigned struct_amr_user_ioctl_sz;
554extern unsigned struct_ap_control_sz;
555extern unsigned struct_apm_ctl_sz;
556extern unsigned struct_apm_event_info_sz;
557extern unsigned struct_apm_power_info_sz;
558extern unsigned struct_atabusiodetach_args_sz;
559extern unsigned struct_atabusioscan_args_sz;
560extern unsigned struct_ath_diag_sz;
561extern unsigned struct_atm_flowmap_sz;
562extern unsigned struct_audio_buf_info_sz;
563extern unsigned struct_audio_device_sz;
564extern unsigned struct_audio_encoding_sz;
565extern unsigned struct_audio_info_sz;
566extern unsigned struct_audio_offset_sz;
567extern unsigned struct_bio_locate_sz;
568extern unsigned struct_bioc_alarm_sz;
569extern unsigned struct_bioc_blink_sz;
570extern unsigned struct_bioc_disk_sz;
571extern unsigned struct_bioc_inq_sz;
572extern unsigned struct_bioc_setstate_sz;
573extern unsigned struct_bioc_vol_sz;
574extern unsigned struct_bioc_volops_sz;
575extern unsigned struct_bktr_chnlset_sz;
576extern unsigned struct_bktr_remote_sz;
577extern unsigned struct_blue_conf_sz;
578extern unsigned struct_blue_interface_sz;
579extern unsigned struct_blue_stats_sz;
580extern unsigned struct_bpf_dltlist_sz;
581extern unsigned struct_bpf_program_sz;
582extern unsigned struct_bpf_stat_old_sz;
583extern unsigned struct_bpf_stat_sz;
584extern unsigned struct_bpf_version_sz;
585extern unsigned struct_btreq_sz;
586extern unsigned struct_btsco_info_sz;
587extern unsigned struct_buffmem_desc_sz;
588extern unsigned struct_cbq_add_class_sz;
589extern unsigned struct_cbq_add_filter_sz;
590extern unsigned struct_cbq_delete_class_sz;
591extern unsigned struct_cbq_delete_filter_sz;
592extern unsigned struct_cbq_getstats_sz;
593extern unsigned struct_cbq_interface_sz;
594extern unsigned struct_cbq_modify_class_sz;
595extern unsigned struct_ccd_ioctl_sz;
596extern unsigned struct_cdnr_add_element_sz;
597extern unsigned struct_cdnr_add_filter_sz;
598extern unsigned struct_cdnr_add_tbmeter_sz;
599extern unsigned struct_cdnr_add_trtcm_sz;
600extern unsigned struct_cdnr_add_tswtcm_sz;
601extern unsigned struct_cdnr_delete_element_sz;
602extern unsigned struct_cdnr_delete_filter_sz;
603extern unsigned struct_cdnr_get_stats_sz;
604extern unsigned struct_cdnr_interface_sz;
605extern unsigned struct_cdnr_modify_tbmeter_sz;
606extern unsigned struct_cdnr_modify_trtcm_sz;
607extern unsigned struct_cdnr_modify_tswtcm_sz;
608extern unsigned struct_cdnr_tbmeter_stats_sz;
609extern unsigned struct_cdnr_tcm_stats_sz;
610extern unsigned struct_cgd_ioctl_sz;
611extern unsigned struct_cgd_user_sz;
612extern unsigned struct_changer_element_status_request_sz;
613extern unsigned struct_changer_exchange_request_sz;
614extern unsigned struct_changer_move_request_sz;
615extern unsigned struct_changer_params_sz;
616extern unsigned struct_changer_position_request_sz;
617extern unsigned struct_changer_set_voltag_request_sz;
618extern unsigned struct_clockctl_adjtime_sz;
619extern unsigned struct_clockctl_clock_settime_sz;
620extern unsigned struct_clockctl_ntp_adjtime_sz;
621extern unsigned struct_clockctl_settimeofday_sz;
622extern unsigned struct_cnwistats_sz;
623extern unsigned struct_cnwitrail_sz;
624extern unsigned struct_cnwstatus_sz;
625extern unsigned struct_count_info_sz;
626extern unsigned struct_cpu_ucode_sz;
627extern unsigned struct_cpu_ucode_version_sz;
628extern unsigned struct_crypt_kop_sz;
629extern unsigned struct_crypt_mkop_sz;
630extern unsigned struct_crypt_mop_sz;
631extern unsigned struct_crypt_op_sz;
632extern unsigned struct_crypt_result_sz;
633extern unsigned struct_crypt_sfop_sz;
634extern unsigned struct_crypt_sgop_sz;
635extern unsigned struct_cryptret_sz;
636extern unsigned struct_devdetachargs_sz;
637extern unsigned struct_devlistargs_sz;
638extern unsigned struct_devpmargs_sz;
639extern unsigned struct_devrescanargs_sz;
640extern unsigned struct_disk_badsecinfo_sz;
641extern unsigned struct_disk_strategy_sz;
642extern unsigned struct_disklabel_sz;
643extern unsigned struct_dkbad_sz;
644extern unsigned struct_dkwedge_info_sz;
645extern unsigned struct_dkwedge_list_sz;
646extern unsigned struct_dmio_setfunc_sz;
647extern unsigned struct_dmx_pes_filter_params_sz;
648extern unsigned struct_dmx_sct_filter_params_sz;
649extern unsigned struct_dmx_stc_sz;
650extern unsigned struct_dvb_diseqc_master_cmd_sz;
651extern unsigned struct_dvb_diseqc_slave_reply_sz;
652extern unsigned struct_dvb_frontend_event_sz;
653extern unsigned struct_dvb_frontend_info_sz;
654extern unsigned struct_dvb_frontend_parameters_sz;
655extern unsigned struct_eccapreq_sz;
656extern unsigned struct_fbcmap_sz;
657extern unsigned struct_fbcurpos_sz;
658extern unsigned struct_fbcursor_sz;
659extern unsigned struct_fbgattr_sz;
660extern unsigned struct_fbsattr_sz;
661extern unsigned struct_fbtype_sz;
662extern unsigned struct_fdformat_cmd_sz;
663extern unsigned struct_fdformat_parms_sz;
664extern unsigned struct_fifoq_conf_sz;
665extern unsigned struct_fifoq_getstats_sz;
666extern unsigned struct_fifoq_interface_sz;
667extern unsigned struct_format_op_sz;
668extern unsigned struct_fss_get_sz;
669extern unsigned struct_fss_set_sz;
670extern unsigned struct_gpio_attach_sz;
671extern unsigned struct_gpio_info_sz;
672extern unsigned struct_gpio_req_sz;
673extern unsigned struct_gpio_set_sz;
674extern unsigned struct_hfsc_add_class_sz;
675extern unsigned struct_hfsc_add_filter_sz;
676extern unsigned struct_hfsc_attach_sz;
677extern unsigned struct_hfsc_class_stats_sz;
678extern unsigned struct_hfsc_delete_class_sz;
679extern unsigned struct_hfsc_delete_filter_sz;
680extern unsigned struct_hfsc_interface_sz;
681extern unsigned struct_hfsc_modify_class_sz;
682extern unsigned struct_hpcfb_dsp_op_sz;
683extern unsigned struct_hpcfb_dspconf_sz;
684extern unsigned struct_hpcfb_fbconf_sz;
685extern unsigned struct_if_addrprefreq_sz;
686extern unsigned struct_if_clonereq_sz;
687extern unsigned struct_if_laddrreq_sz;
688extern unsigned struct_ifaddr_sz;
689extern unsigned struct_ifaliasreq_sz;
690extern unsigned struct_ifcapreq_sz;
691extern unsigned struct_ifconf_sz;
692extern unsigned struct_ifdatareq_sz;
693extern unsigned struct_ifdrv_sz;
694extern unsigned struct_ifmediareq_sz;
695extern unsigned struct_ifpppcstatsreq_sz;
696extern unsigned struct_ifpppstatsreq_sz;
697extern unsigned struct_ifreq_sz;
698extern unsigned struct_in6_addrpolicy_sz;
699extern unsigned struct_in6_ndireq_sz;
700extern unsigned struct_ioc_load_unload_sz;
701extern unsigned struct_ioc_patch_sz;
702extern unsigned struct_ioc_play_blocks_sz;
703extern unsigned struct_ioc_play_msf_sz;
704extern unsigned struct_ioc_play_track_sz;
705extern unsigned struct_ioc_read_subchannel_sz;
706extern unsigned struct_ioc_read_toc_entry_sz;
707extern unsigned struct_ioc_toc_header_sz;
708extern unsigned struct_ioc_vol_sz;
709extern unsigned struct_ioctl_pt_sz;
710extern unsigned struct_ioppt_sz;
711extern unsigned struct_iovec_sz;
712extern unsigned struct_ipfobj_sz;
713extern unsigned struct_irda_params_sz;
714extern unsigned struct_isp_fc_device_sz;
715extern unsigned struct_isp_fc_tsk_mgmt_sz;
716extern unsigned struct_isp_hba_device_sz;
717extern unsigned struct_isv_cmd_sz;
718extern unsigned struct_jobs_add_class_sz;
719extern unsigned struct_jobs_add_filter_sz;
720extern unsigned struct_jobs_attach_sz;
721extern unsigned struct_jobs_class_stats_sz;
722extern unsigned struct_jobs_delete_class_sz;
723extern unsigned struct_jobs_delete_filter_sz;
724extern unsigned struct_jobs_interface_sz;
725extern unsigned struct_jobs_modify_class_sz;
726extern unsigned struct_kbentry_sz;
727extern unsigned struct_kfilter_mapping_sz;
728extern unsigned struct_kiockeymap_sz;
729extern unsigned struct_ksyms_gsymbol_sz;
730extern unsigned struct_ksyms_gvalue_sz;
731extern unsigned struct_ksyms_ogsymbol_sz;
732extern unsigned struct_kttcp_io_args_sz;
733extern unsigned struct_ltchars_sz;
734extern unsigned struct_lua_create_sz;
735extern unsigned struct_lua_info_sz;
736extern unsigned struct_lua_load_sz;
737extern unsigned struct_lua_require_sz;
738extern unsigned struct_mbpp_param_sz;
739extern unsigned struct_md_conf_sz;
740extern unsigned struct_meteor_capframe_sz;
741extern unsigned struct_meteor_counts_sz;
742extern unsigned struct_meteor_geomet_sz;
743extern unsigned struct_meteor_pixfmt_sz;
744extern unsigned struct_meteor_video_sz;
745extern unsigned struct_mlx_cinfo_sz;
746extern unsigned struct_mlx_pause_sz;
747extern unsigned struct_mlx_rebuild_request_sz;
748extern unsigned struct_mlx_rebuild_status_sz;
749extern unsigned struct_mlx_usercommand_sz;
750extern unsigned struct_mly_user_command_sz;
751extern unsigned struct_mly_user_health_sz;
752extern unsigned struct_mtget_sz;
753extern unsigned struct_mtop_sz;
754extern unsigned struct_npf_ioctl_table_sz;
755extern unsigned struct_npioctl_sz;
756extern unsigned struct_nvme_pt_command_sz;
757extern unsigned struct_ochanger_element_status_request_sz;
758extern unsigned struct_ofiocdesc_sz;
759extern unsigned struct_okiockey_sz;
760extern unsigned struct_ortentry_sz;
761extern unsigned struct_oscsi_addr_sz;
762extern unsigned struct_oss_audioinfo_sz;
763extern unsigned struct_oss_sysinfo_sz;
764extern unsigned struct_pciio_bdf_cfgreg_sz;
765extern unsigned struct_pciio_businfo_sz;
766extern unsigned struct_pciio_cfgreg_sz;
767extern unsigned struct_pciio_drvname_sz;
768extern unsigned struct_pciio_drvnameonbus_sz;
769extern unsigned struct_pcvtid_sz;
770extern unsigned struct_pf_osfp_ioctl_sz;
771extern unsigned struct_pf_status_sz;
772extern unsigned struct_pfioc_altq_sz;
773extern unsigned struct_pfioc_if_sz;
774extern unsigned struct_pfioc_iface_sz;
775extern unsigned struct_pfioc_limit_sz;
776extern unsigned struct_pfioc_natlook_sz;
777extern unsigned struct_pfioc_pooladdr_sz;
778extern unsigned struct_pfioc_qstats_sz;
779extern unsigned struct_pfioc_rule_sz;
780extern unsigned struct_pfioc_ruleset_sz;
781extern unsigned struct_pfioc_src_node_kill_sz;
782extern unsigned struct_pfioc_src_nodes_sz;
783extern unsigned struct_pfioc_state_kill_sz;
784extern unsigned struct_pfioc_state_sz;
785extern unsigned struct_pfioc_states_sz;
786extern unsigned struct_pfioc_table_sz;
787extern unsigned struct_pfioc_tm_sz;
788extern unsigned struct_pfioc_trans_sz;
789extern unsigned struct_plistref_sz;
790extern unsigned struct_power_type_sz;
791extern unsigned struct_ppp_idle_sz;
792extern unsigned struct_ppp_option_data_sz;
793extern unsigned struct_ppp_rawin_sz;
794extern unsigned struct_pppoeconnectionstate_sz;
795extern unsigned struct_pppoediscparms_sz;
796extern unsigned struct_priq_add_class_sz;
797extern unsigned struct_priq_add_filter_sz;
798extern unsigned struct_priq_class_stats_sz;
799extern unsigned struct_priq_delete_class_sz;
800extern unsigned struct_priq_delete_filter_sz;
801extern unsigned struct_priq_interface_sz;
802extern unsigned struct_priq_modify_class_sz;
803extern unsigned struct_ptmget_sz;
804extern unsigned struct_pvctxreq_sz;
805extern unsigned struct_radio_info_sz;
806extern unsigned struct_red_conf_sz;
807extern unsigned struct_red_interface_sz;
808extern unsigned struct_red_stats_sz;
809extern unsigned struct_redparams_sz;
810extern unsigned struct_rf_pmparams_sz;
811extern unsigned struct_rf_pmstat_sz;
812extern unsigned struct_rf_recon_req_sz;
813extern unsigned struct_rio_conf_sz;
814extern unsigned struct_rio_interface_sz;
815extern unsigned struct_rio_stats_sz;
816extern unsigned struct_scan_io_sz;
817extern unsigned struct_scbusaccel_args_sz;
818extern unsigned struct_scbusiodetach_args_sz;
819extern unsigned struct_scbusioscan_args_sz;
820extern unsigned struct_scsi_addr_sz;
821extern unsigned struct_seq_event_rec_sz;
822extern unsigned struct_session_op_sz;
823extern unsigned struct_sgttyb_sz;
824extern unsigned struct_sioc_sg_req_sz;
825extern unsigned struct_sioc_vif_req_sz;
826extern unsigned struct_smbioc_flags_sz;
827extern unsigned struct_smbioc_lookup_sz;
828extern unsigned struct_smbioc_oshare_sz;
829extern unsigned struct_smbioc_ossn_sz;
830extern unsigned struct_smbioc_rq_sz;
831extern unsigned struct_smbioc_rw_sz;
832extern unsigned struct_spppauthcfg_sz;
833extern unsigned struct_spppauthfailuresettings_sz;
834extern unsigned struct_spppauthfailurestats_sz;
835extern unsigned struct_spppdnsaddrs_sz;
836extern unsigned struct_spppdnssettings_sz;
837extern unsigned struct_spppidletimeout_sz;
838extern unsigned struct_spppkeepalivesettings_sz;
839extern unsigned struct_sppplcpcfg_sz;
840extern unsigned struct_spppstatus_sz;
841extern unsigned struct_spppstatusncp_sz;
842extern unsigned struct_srt_rt_sz;
843extern unsigned struct_stic_xinfo_sz;
844extern unsigned struct_sun_dkctlr_sz;
845extern unsigned struct_sun_dkgeom_sz;
846extern unsigned struct_sun_dkpart_sz;
847extern unsigned struct_synth_info_sz;
848extern unsigned struct_tbrreq_sz;
849extern unsigned struct_tchars_sz;
850extern unsigned struct_termios_sz;
851extern unsigned struct_timeval_sz;
852extern unsigned struct_twe_drivecommand_sz;
853extern unsigned struct_twe_paramcommand_sz;
854extern unsigned struct_twe_usercommand_sz;
855extern unsigned struct_ukyopon_identify_sz;
856extern unsigned struct_urio_command_sz;
857extern unsigned struct_usb_alt_interface_sz;
858extern unsigned struct_usb_bulk_ra_wb_opt_sz;
859extern unsigned struct_usb_config_desc_sz;
860extern unsigned struct_usb_ctl_report_desc_sz;
861extern unsigned struct_usb_ctl_report_sz;
862extern unsigned struct_usb_ctl_request_sz;
863#if defined(__x86_64__)
864extern unsigned struct_nvmm_ioc_capability_sz;
865extern unsigned struct_nvmm_ioc_machine_create_sz;
866extern unsigned struct_nvmm_ioc_machine_destroy_sz;
867extern unsigned struct_nvmm_ioc_machine_configure_sz;
868extern unsigned struct_nvmm_ioc_vcpu_create_sz;
869extern unsigned struct_nvmm_ioc_vcpu_destroy_sz;
870extern unsigned struct_nvmm_ioc_vcpu_configure_sz;
871extern unsigned struct_nvmm_ioc_vcpu_setstate_sz;
872extern unsigned struct_nvmm_ioc_vcpu_getstate_sz;
873extern unsigned struct_nvmm_ioc_vcpu_inject_sz;
874extern unsigned struct_nvmm_ioc_vcpu_run_sz;
875extern unsigned struct_nvmm_ioc_gpa_map_sz;
876extern unsigned struct_nvmm_ioc_gpa_unmap_sz;
877extern unsigned struct_nvmm_ioc_hva_map_sz;
878extern unsigned struct_nvmm_ioc_hva_unmap_sz;
879extern unsigned struct_nvmm_ioc_ctl_sz;
880#endif
881extern unsigned struct_spi_ioctl_configure_sz;
882extern unsigned struct_spi_ioctl_transfer_sz;
883extern unsigned struct_autofs_daemon_request_sz;
884extern unsigned struct_autofs_daemon_done_sz;
885extern unsigned struct_sctp_connectx_addrs_sz;
886extern unsigned struct_usb_device_info_old_sz;
887extern unsigned struct_usb_device_info_sz;
888extern unsigned struct_usb_device_stats_sz;
889extern unsigned struct_usb_endpoint_desc_sz;
890extern unsigned struct_usb_full_desc_sz;
891extern unsigned struct_usb_interface_desc_sz;
892extern unsigned struct_usb_string_desc_sz;
893extern unsigned struct_utoppy_readfile_sz;
894extern unsigned struct_utoppy_rename_sz;
895extern unsigned struct_utoppy_stats_sz;
896extern unsigned struct_utoppy_writefile_sz;
897extern unsigned struct_v4l2_audio_sz;
898extern unsigned struct_v4l2_audioout_sz;
899extern unsigned struct_v4l2_buffer_sz;
900extern unsigned struct_v4l2_capability_sz;
901extern unsigned struct_v4l2_control_sz;
902extern unsigned struct_v4l2_crop_sz;
903extern unsigned struct_v4l2_cropcap_sz;
904extern unsigned struct_v4l2_fmtdesc_sz;
905extern unsigned struct_v4l2_format_sz;
906extern unsigned struct_v4l2_framebuffer_sz;
907extern unsigned struct_v4l2_frequency_sz;
908extern unsigned struct_v4l2_frmivalenum_sz;
909extern unsigned struct_v4l2_frmsizeenum_sz;
910extern unsigned struct_v4l2_input_sz;
911extern unsigned struct_v4l2_jpegcompression_sz;
912extern unsigned struct_v4l2_modulator_sz;
913extern unsigned struct_v4l2_output_sz;
914extern unsigned struct_v4l2_queryctrl_sz;
915extern unsigned struct_v4l2_querymenu_sz;
916extern unsigned struct_v4l2_requestbuffers_sz;
917extern unsigned struct_v4l2_standard_sz;
918extern unsigned struct_v4l2_streamparm_sz;
919extern unsigned struct_v4l2_tuner_sz;
920extern unsigned struct_vnd_ioctl_sz;
921extern unsigned struct_vnd_user_sz;
922extern unsigned struct_vt_stat_sz;
923extern unsigned struct_wdog_conf_sz;
924extern unsigned struct_wdog_mode_sz;
925extern unsigned struct_ipmi_recv_sz;
926extern unsigned struct_ipmi_req_sz;
927extern unsigned struct_ipmi_cmdspec_sz;
928extern unsigned struct_wfq_conf_sz;
929extern unsigned struct_wfq_getqid_sz;
930extern unsigned struct_wfq_getstats_sz;
931extern unsigned struct_wfq_interface_sz;
932extern unsigned struct_wfq_setweight_sz;
933extern unsigned struct_winsize_sz;
934extern unsigned struct_wscons_event_sz;
935extern unsigned struct_wsdisplay_addscreendata_sz;
936extern unsigned struct_wsdisplay_char_sz;
937extern unsigned struct_wsdisplay_cmap_sz;
938extern unsigned struct_wsdisplay_curpos_sz;
939extern unsigned struct_wsdisplay_cursor_sz;
940extern unsigned struct_wsdisplay_delscreendata_sz;
941extern unsigned struct_wsdisplay_fbinfo_sz;
942extern unsigned struct_wsdisplay_font_sz;
943extern unsigned struct_wsdisplay_kbddata_sz;
944extern unsigned struct_wsdisplay_msgattrs_sz;
945extern unsigned struct_wsdisplay_param_sz;
946extern unsigned struct_wsdisplay_scroll_data_sz;
947extern unsigned struct_wsdisplay_usefontdata_sz;
948extern unsigned struct_wsdisplayio_blit_sz;
949extern unsigned struct_wsdisplayio_bus_id_sz;
950extern unsigned struct_wsdisplayio_edid_info_sz;
951extern unsigned struct_wsdisplayio_fbinfo_sz;
952extern unsigned struct_wskbd_bell_data_sz;
953extern unsigned struct_wskbd_keyrepeat_data_sz;
954extern unsigned struct_wskbd_map_data_sz;
955extern unsigned struct_wskbd_scroll_data_sz;
956extern unsigned struct_wsmouse_calibcoords_sz;
957extern unsigned struct_wsmouse_id_sz;
958extern unsigned struct_wsmouse_repeat_sz;
959extern unsigned struct_wsmux_device_list_sz;
960extern unsigned struct_wsmux_device_sz;
961extern unsigned struct_xd_iocmd_sz;
962
963extern unsigned struct_scsireq_sz;
964extern unsigned struct_tone_sz;
965extern unsigned union_twe_statrequest_sz;
966extern unsigned struct_usb_device_descriptor_sz;
967extern unsigned struct_vt_mode_sz;
968extern unsigned struct__old_mixer_info_sz;
969extern unsigned struct__agp_allocate_sz;
970extern unsigned struct__agp_bind_sz;
971extern unsigned struct__agp_info_sz;
972extern unsigned struct__agp_setup_sz;
973extern unsigned struct__agp_unbind_sz;
974extern unsigned struct_atareq_sz;
975extern unsigned struct_cpustate_sz;
976extern unsigned struct_dmx_caps_sz;
977extern unsigned enum_dmx_source_sz;
978extern unsigned union_dvd_authinfo_sz;
979extern unsigned union_dvd_struct_sz;
980extern unsigned enum_v4l2_priority_sz;
981extern unsigned struct_envsys_basic_info_sz;
982extern unsigned struct_envsys_tre_data_sz;
983extern unsigned enum_fe_sec_mini_cmd_sz;
984extern unsigned enum_fe_sec_tone_mode_sz;
985extern unsigned enum_fe_sec_voltage_sz;
986extern unsigned enum_fe_status_sz;
987extern unsigned struct_gdt_ctrt_sz;
988extern unsigned struct_gdt_event_sz;
989extern unsigned struct_gdt_osv_sz;
990extern unsigned struct_gdt_rescan_sz;
991extern unsigned struct_gdt_statist_sz;
992extern unsigned struct_gdt_ucmd_sz;
993extern unsigned struct_iscsi_conn_status_parameters_sz;
994extern unsigned struct_iscsi_get_version_parameters_sz;
995extern unsigned struct_iscsi_iocommand_parameters_sz;
996extern unsigned struct_iscsi_login_parameters_sz;
997extern unsigned struct_iscsi_logout_parameters_sz;
998extern unsigned struct_iscsi_register_event_parameters_sz;
999extern unsigned struct_iscsi_remove_parameters_sz;
1000extern unsigned struct_iscsi_send_targets_parameters_sz;
1001extern unsigned struct_iscsi_set_node_name_parameters_sz;
1002extern unsigned struct_iscsi_wait_event_parameters_sz;
1003extern unsigned struct_isp_stats_sz;
1004extern unsigned struct_lsenable_sz;
1005extern unsigned struct_lsdisable_sz;
1006extern unsigned struct_audio_format_query_sz;
1007extern unsigned struct_mixer_ctrl_sz;
1008extern unsigned struct_mixer_devinfo_sz;
1009extern unsigned struct_mpu_command_rec_sz;
1010extern unsigned struct_rndstat_sz;
1011extern unsigned struct_rndstat_name_sz;
1012extern unsigned struct_rndctl_sz;
1013extern unsigned struct_rnddata_sz;
1014extern unsigned struct_rndpoolstat_sz;
1015extern unsigned struct_rndstat_est_sz;
1016extern unsigned struct_rndstat_est_name_sz;
1017extern unsigned struct_pps_params_sz;
1018extern unsigned struct_pps_info_sz;
1019extern unsigned struct_mixer_info_sz;
1020extern unsigned struct_RF_SparetWait_sz;
1021extern unsigned struct_RF_ComponentLabel_sz;
1022extern unsigned struct_RF_SingleComponent_sz;
1023extern unsigned struct_RF_ProgressInfo_sz;
1024extern unsigned struct_nvlist_ref_sz;
1025extern unsigned struct_StringList_sz;
1026
1027
1028// A special value to mark ioctls that are not present on the target platform,
1029// when it can not be determined without including any system headers.
1030extern const unsigned IOCTL_NOT_PRESENT;
1031
1032
1033extern unsigned IOCTL_AFM_ADDFMAP;
1034extern unsigned IOCTL_AFM_DELFMAP;
1035extern unsigned IOCTL_AFM_CLEANFMAP;
1036extern unsigned IOCTL_AFM_GETFMAP;
1037extern unsigned IOCTL_ALTQGTYPE;
1038extern unsigned IOCTL_ALTQTBRSET;
1039extern unsigned IOCTL_ALTQTBRGET;
1040extern unsigned IOCTL_BLUE_IF_ATTACH;
1041extern unsigned IOCTL_BLUE_IF_DETACH;
1042extern unsigned IOCTL_BLUE_ENABLE;
1043extern unsigned IOCTL_BLUE_DISABLE;
1044extern unsigned IOCTL_BLUE_CONFIG;
1045extern unsigned IOCTL_BLUE_GETSTATS;
1046extern unsigned IOCTL_CBQ_IF_ATTACH;
1047extern unsigned IOCTL_CBQ_IF_DETACH;
1048extern unsigned IOCTL_CBQ_ENABLE;
1049extern unsigned IOCTL_CBQ_DISABLE;
1050extern unsigned IOCTL_CBQ_CLEAR_HIERARCHY;
1051extern unsigned IOCTL_CBQ_ADD_CLASS;
1052extern unsigned IOCTL_CBQ_DEL_CLASS;
1053extern unsigned IOCTL_CBQ_MODIFY_CLASS;
1054extern unsigned IOCTL_CBQ_ADD_FILTER;
1055extern unsigned IOCTL_CBQ_DEL_FILTER;
1056extern unsigned IOCTL_CBQ_GETSTATS;
1057extern unsigned IOCTL_CDNR_IF_ATTACH;
1058extern unsigned IOCTL_CDNR_IF_DETACH;
1059extern unsigned IOCTL_CDNR_ENABLE;
1060extern unsigned IOCTL_CDNR_DISABLE;
1061extern unsigned IOCTL_CDNR_ADD_FILTER;
1062extern unsigned IOCTL_CDNR_DEL_FILTER;
1063extern unsigned IOCTL_CDNR_GETSTATS;
1064extern unsigned IOCTL_CDNR_ADD_ELEM;
1065extern unsigned IOCTL_CDNR_DEL_ELEM;
1066extern unsigned IOCTL_CDNR_ADD_TBM;
1067extern unsigned IOCTL_CDNR_MOD_TBM;
1068extern unsigned IOCTL_CDNR_TBM_STATS;
1069extern unsigned IOCTL_CDNR_ADD_TCM;
1070extern unsigned IOCTL_CDNR_MOD_TCM;
1071extern unsigned IOCTL_CDNR_TCM_STATS;
1072extern unsigned IOCTL_CDNR_ADD_TSW;
1073extern unsigned IOCTL_CDNR_MOD_TSW;
1074extern unsigned IOCTL_FIFOQ_IF_ATTACH;
1075extern unsigned IOCTL_FIFOQ_IF_DETACH;
1076extern unsigned IOCTL_FIFOQ_ENABLE;
1077extern unsigned IOCTL_FIFOQ_DISABLE;
1078extern unsigned IOCTL_FIFOQ_CONFIG;
1079extern unsigned IOCTL_FIFOQ_GETSTATS;
1080extern unsigned IOCTL_HFSC_IF_ATTACH;
1081extern unsigned IOCTL_HFSC_IF_DETACH;
1082extern unsigned IOCTL_HFSC_ENABLE;
1083extern unsigned IOCTL_HFSC_DISABLE;
1084extern unsigned IOCTL_HFSC_CLEAR_HIERARCHY;
1085extern unsigned IOCTL_HFSC_ADD_CLASS;
1086extern unsigned IOCTL_HFSC_DEL_CLASS;
1087extern unsigned IOCTL_HFSC_MOD_CLASS;
1088extern unsigned IOCTL_HFSC_ADD_FILTER;
1089extern unsigned IOCTL_HFSC_DEL_FILTER;
1090extern unsigned IOCTL_HFSC_GETSTATS;
1091extern unsigned IOCTL_JOBS_IF_ATTACH;
1092extern unsigned IOCTL_JOBS_IF_DETACH;
1093extern unsigned IOCTL_JOBS_ENABLE;
1094extern unsigned IOCTL_JOBS_DISABLE;
1095extern unsigned IOCTL_JOBS_CLEAR;
1096extern unsigned IOCTL_JOBS_ADD_CLASS;
1097extern unsigned IOCTL_JOBS_DEL_CLASS;
1098extern unsigned IOCTL_JOBS_MOD_CLASS;
1099extern unsigned IOCTL_JOBS_ADD_FILTER;
1100extern unsigned IOCTL_JOBS_DEL_FILTER;
1101extern unsigned IOCTL_JOBS_GETSTATS;
1102extern unsigned IOCTL_PRIQ_IF_ATTACH;
1103extern unsigned IOCTL_PRIQ_IF_DETACH;
1104extern unsigned IOCTL_PRIQ_ENABLE;
1105extern unsigned IOCTL_PRIQ_DISABLE;
1106extern unsigned IOCTL_PRIQ_CLEAR;
1107extern unsigned IOCTL_PRIQ_ADD_CLASS;
1108extern unsigned IOCTL_PRIQ_DEL_CLASS;
1109extern unsigned IOCTL_PRIQ_MOD_CLASS;
1110extern unsigned IOCTL_PRIQ_ADD_FILTER;
1111extern unsigned IOCTL_PRIQ_DEL_FILTER;
1112extern unsigned IOCTL_PRIQ_GETSTATS;
1113extern unsigned IOCTL_RED_IF_ATTACH;
1114extern unsigned IOCTL_RED_IF_DETACH;
1115extern unsigned IOCTL_RED_ENABLE;
1116extern unsigned IOCTL_RED_DISABLE;
1117extern unsigned IOCTL_RED_CONFIG;
1118extern unsigned IOCTL_RED_GETSTATS;
1119extern unsigned IOCTL_RED_SETDEFAULTS;
1120extern unsigned IOCTL_RIO_IF_ATTACH;
1121extern unsigned IOCTL_RIO_IF_DETACH;
1122extern unsigned IOCTL_RIO_ENABLE;
1123extern unsigned IOCTL_RIO_DISABLE;
1124extern unsigned IOCTL_RIO_CONFIG;
1125extern unsigned IOCTL_RIO_GETSTATS;
1126extern unsigned IOCTL_RIO_SETDEFAULTS;
1127extern unsigned IOCTL_WFQ_IF_ATTACH;
1128extern unsigned IOCTL_WFQ_IF_DETACH;
1129extern unsigned IOCTL_WFQ_ENABLE;
1130extern unsigned IOCTL_WFQ_DISABLE;
1131extern unsigned IOCTL_WFQ_CONFIG;
1132extern unsigned IOCTL_WFQ_GET_STATS;
1133extern unsigned IOCTL_WFQ_GET_QID;
1134extern unsigned IOCTL_WFQ_SET_WEIGHT;
1135extern unsigned IOCTL_CRIOGET;
1136extern unsigned IOCTL_CIOCFSESSION;
1137extern unsigned IOCTL_CIOCKEY;
1138extern unsigned IOCTL_CIOCNFKEYM;
1139extern unsigned IOCTL_CIOCNFSESSION;
1140extern unsigned IOCTL_CIOCNCRYPTRETM;
1141extern unsigned IOCTL_CIOCNCRYPTRET;
1142extern unsigned IOCTL_CIOCGSESSION;
1143extern unsigned IOCTL_CIOCNGSESSION;
1144extern unsigned IOCTL_CIOCCRYPT;
1145extern unsigned IOCTL_CIOCNCRYPTM;
1146extern unsigned IOCTL_CIOCASYMFEAT;
1147extern unsigned IOCTL_APM_IOC_REJECT;
1148extern unsigned IOCTL_APM_IOC_STANDBY;
1149extern unsigned IOCTL_APM_IOC_SUSPEND;
1150extern unsigned IOCTL_OAPM_IOC_GETPOWER;
1151extern unsigned IOCTL_APM_IOC_GETPOWER;
1152extern unsigned IOCTL_APM_IOC_NEXTEVENT;
1153extern unsigned IOCTL_APM_IOC_DEV_CTL;
1154extern unsigned IOCTL_NETBSD_DM_IOCTL;
1155extern unsigned IOCTL_DMIO_SETFUNC;
1156extern unsigned IOCTL_DMX_START;
1157extern unsigned IOCTL_DMX_STOP;
1158extern unsigned IOCTL_DMX_SET_FILTER;
1159extern unsigned IOCTL_DMX_SET_PES_FILTER;
1160extern unsigned IOCTL_DMX_SET_BUFFER_SIZE;
1161extern unsigned IOCTL_DMX_GET_STC;
1162extern unsigned IOCTL_DMX_ADD_PID;
1163extern unsigned IOCTL_DMX_REMOVE_PID;
1164extern unsigned IOCTL_DMX_GET_CAPS;
1165extern unsigned IOCTL_DMX_SET_SOURCE;
1166extern unsigned IOCTL_FE_READ_STATUS;
1167extern unsigned IOCTL_FE_READ_BER;
1168extern unsigned IOCTL_FE_READ_SNR;
1169extern unsigned IOCTL_FE_READ_SIGNAL_STRENGTH;
1170extern unsigned IOCTL_FE_READ_UNCORRECTED_BLOCKS;
1171extern unsigned IOCTL_FE_SET_FRONTEND;
1172extern unsigned IOCTL_FE_GET_FRONTEND;
1173extern unsigned IOCTL_FE_GET_EVENT;
1174extern unsigned IOCTL_FE_GET_INFO;
1175extern unsigned IOCTL_FE_DISEQC_RESET_OVERLOAD;
1176extern unsigned IOCTL_FE_DISEQC_SEND_MASTER_CMD;
1177extern unsigned IOCTL_FE_DISEQC_RECV_SLAVE_REPLY;
1178extern unsigned IOCTL_FE_DISEQC_SEND_BURST;
1179extern unsigned IOCTL_FE_SET_TONE;
1180extern unsigned IOCTL_FE_SET_VOLTAGE;
1181extern unsigned IOCTL_FE_ENABLE_HIGH_LNB_VOLTAGE;
1182extern unsigned IOCTL_FE_SET_FRONTEND_TUNE_MODE;
1183extern unsigned IOCTL_FE_DISHNETWORK_SEND_LEGACY_CMD;
1184extern unsigned IOCTL_FILEMON_SET_FD;
1185extern unsigned IOCTL_FILEMON_SET_PID;
1186extern unsigned IOCTL_HDAUDIO_FGRP_INFO;
1187extern unsigned IOCTL_HDAUDIO_FGRP_GETCONFIG;
1188extern unsigned IOCTL_HDAUDIO_FGRP_SETCONFIG;
1189extern unsigned IOCTL_HDAUDIO_FGRP_WIDGET_INFO;
1190extern unsigned IOCTL_HDAUDIO_FGRP_CODEC_INFO;
1191extern unsigned IOCTL_HDAUDIO_AFG_WIDGET_INFO;
1192extern unsigned IOCTL_HDAUDIO_AFG_CODEC_INFO;
1193extern unsigned IOCTL_CEC_GET_PHYS_ADDR;
1194extern unsigned IOCTL_CEC_GET_LOG_ADDRS;
1195extern unsigned IOCTL_CEC_SET_LOG_ADDRS;
1196extern unsigned IOCTL_CEC_GET_VENDOR_ID;
1197extern unsigned IOCTL_HPCFBIO_GCONF;
1198extern unsigned IOCTL_HPCFBIO_SCONF;
1199extern unsigned IOCTL_HPCFBIO_GDSPCONF;
1200extern unsigned IOCTL_HPCFBIO_SDSPCONF;
1201extern unsigned IOCTL_HPCFBIO_GOP;
1202extern unsigned IOCTL_HPCFBIO_SOP;
1203extern unsigned IOCTL_IOPIOCPT;
1204extern unsigned IOCTL_IOPIOCGLCT;
1205extern unsigned IOCTL_IOPIOCGSTATUS;
1206extern unsigned IOCTL_IOPIOCRECONFIG;
1207extern unsigned IOCTL_IOPIOCGTIDMAP;
1208extern unsigned IOCTL_SIOCGATHSTATS;
1209extern unsigned IOCTL_SIOCGATHDIAG;
1210extern unsigned IOCTL_METEORCAPTUR;
1211extern unsigned IOCTL_METEORCAPFRM;
1212extern unsigned IOCTL_METEORSETGEO;
1213extern unsigned IOCTL_METEORGETGEO;
1214extern unsigned IOCTL_METEORSTATUS;
1215extern unsigned IOCTL_METEORSHUE;
1216extern unsigned IOCTL_METEORGHUE;
1217extern unsigned IOCTL_METEORSFMT;
1218extern unsigned IOCTL_METEORGFMT;
1219extern unsigned IOCTL_METEORSINPUT;
1220extern unsigned IOCTL_METEORGINPUT;
1221extern unsigned IOCTL_METEORSCHCV;
1222extern unsigned IOCTL_METEORGCHCV;
1223extern unsigned IOCTL_METEORSCOUNT;
1224extern unsigned IOCTL_METEORGCOUNT;
1225extern unsigned IOCTL_METEORSFPS;
1226extern unsigned IOCTL_METEORGFPS;
1227extern unsigned IOCTL_METEORSSIGNAL;
1228extern unsigned IOCTL_METEORGSIGNAL;
1229extern unsigned IOCTL_METEORSVIDEO;
1230extern unsigned IOCTL_METEORGVIDEO;
1231extern unsigned IOCTL_METEORSBRIG;
1232extern unsigned IOCTL_METEORGBRIG;
1233extern unsigned IOCTL_METEORSCSAT;
1234extern unsigned IOCTL_METEORGCSAT;
1235extern unsigned IOCTL_METEORSCONT;
1236extern unsigned IOCTL_METEORGCONT;
1237extern unsigned IOCTL_METEORSHWS;
1238extern unsigned IOCTL_METEORGHWS;
1239extern unsigned IOCTL_METEORSVWS;
1240extern unsigned IOCTL_METEORGVWS;
1241extern unsigned IOCTL_METEORSTS;
1242extern unsigned IOCTL_METEORGTS;
1243extern unsigned IOCTL_TVTUNER_SETCHNL;
1244extern unsigned IOCTL_TVTUNER_GETCHNL;
1245extern unsigned IOCTL_TVTUNER_SETTYPE;
1246extern unsigned IOCTL_TVTUNER_GETTYPE;
1247extern unsigned IOCTL_TVTUNER_GETSTATUS;
1248extern unsigned IOCTL_TVTUNER_SETFREQ;
1249extern unsigned IOCTL_TVTUNER_GETFREQ;
1250extern unsigned IOCTL_TVTUNER_SETAFC;
1251extern unsigned IOCTL_TVTUNER_GETAFC;
1252extern unsigned IOCTL_RADIO_SETMODE;
1253extern unsigned IOCTL_RADIO_GETMODE;
1254extern unsigned IOCTL_RADIO_SETFREQ;
1255extern unsigned IOCTL_RADIO_GETFREQ;
1256extern unsigned IOCTL_METEORSACTPIXFMT;
1257extern unsigned IOCTL_METEORGACTPIXFMT;
1258extern unsigned IOCTL_METEORGSUPPIXFMT;
1259extern unsigned IOCTL_TVTUNER_GETCHNLSET;
1260extern unsigned IOCTL_REMOTE_GETKEY;
1261extern unsigned IOCTL_GDT_IOCTL_GENERAL;
1262extern unsigned IOCTL_GDT_IOCTL_DRVERS;
1263extern unsigned IOCTL_GDT_IOCTL_CTRTYPE;
1264extern unsigned IOCTL_GDT_IOCTL_OSVERS;
1265extern unsigned IOCTL_GDT_IOCTL_CTRCNT;
1266extern unsigned IOCTL_GDT_IOCTL_EVENT;
1267extern unsigned IOCTL_GDT_IOCTL_STATIST;
1268extern unsigned IOCTL_GDT_IOCTL_RESCAN;
1269extern unsigned IOCTL_ISP_SDBLEV;
1270extern unsigned IOCTL_ISP_RESETHBA;
1271extern unsigned IOCTL_ISP_RESCAN;
1272extern unsigned IOCTL_ISP_SETROLE;
1273extern unsigned IOCTL_ISP_GETROLE;
1274extern unsigned IOCTL_ISP_GET_STATS;
1275extern unsigned IOCTL_ISP_CLR_STATS;
1276extern unsigned IOCTL_ISP_FC_LIP;
1277extern unsigned IOCTL_ISP_FC_GETDINFO;
1278extern unsigned IOCTL_ISP_GET_FW_CRASH_DUMP;
1279extern unsigned IOCTL_ISP_FORCE_CRASH_DUMP;
1280extern unsigned IOCTL_ISP_FC_GETHINFO;
1281extern unsigned IOCTL_ISP_TSK_MGMT;
1282extern unsigned IOCTL_ISP_FC_GETDLIST;
1283extern unsigned IOCTL_MLXD_STATUS;
1284extern unsigned IOCTL_MLXD_CHECKASYNC;
1285extern unsigned IOCTL_MLXD_DETACH;
1286extern unsigned IOCTL_MLX_RESCAN_DRIVES;
1287extern unsigned IOCTL_MLX_PAUSE_CHANNEL;
1288extern unsigned IOCTL_MLX_COMMAND;
1289extern unsigned IOCTL_MLX_REBUILDASYNC;
1290extern unsigned IOCTL_MLX_REBUILDSTAT;
1291extern unsigned IOCTL_MLX_GET_SYSDRIVE;
1292extern unsigned IOCTL_MLX_GET_CINFO;
1293extern unsigned IOCTL_NVME_PASSTHROUGH_CMD;
1294extern unsigned IOCTL_FWCFGIO_SET_INDEX;
1295extern unsigned IOCTL_IRDA_RESET_PARAMS;
1296extern unsigned IOCTL_IRDA_SET_PARAMS;
1297extern unsigned IOCTL_IRDA_GET_SPEEDMASK;
1298extern unsigned IOCTL_IRDA_GET_TURNAROUNDMASK;
1299extern unsigned IOCTL_IRFRAMETTY_GET_DEVICE;
1300extern unsigned IOCTL_IRFRAMETTY_GET_DONGLE;
1301extern unsigned IOCTL_IRFRAMETTY_SET_DONGLE;
1302extern unsigned IOCTL_ISV_CMD;
1303extern unsigned IOCTL_WTQICMD;
1304extern unsigned IOCTL_ISCSI_GET_VERSION;
1305extern unsigned IOCTL_ISCSI_LOGIN;
1306extern unsigned IOCTL_ISCSI_LOGOUT;
1307extern unsigned IOCTL_ISCSI_ADD_CONNECTION;
1308extern unsigned IOCTL_ISCSI_RESTORE_CONNECTION;
1309extern unsigned IOCTL_ISCSI_REMOVE_CONNECTION;
1310extern unsigned IOCTL_ISCSI_CONNECTION_STATUS;
1311extern unsigned IOCTL_ISCSI_SEND_TARGETS;
1312extern unsigned IOCTL_ISCSI_SET_NODE_NAME;
1313extern unsigned IOCTL_ISCSI_IO_COMMAND;
1314extern unsigned IOCTL_ISCSI_REGISTER_EVENT;
1315extern unsigned IOCTL_ISCSI_DEREGISTER_EVENT;
1316extern unsigned IOCTL_ISCSI_WAIT_EVENT;
1317extern unsigned IOCTL_ISCSI_POLL_EVENT;
1318extern unsigned IOCTL_OFIOCGET;
1319extern unsigned IOCTL_OFIOCSET;
1320extern unsigned IOCTL_OFIOCNEXTPROP;
1321extern unsigned IOCTL_OFIOCGETOPTNODE;
1322extern unsigned IOCTL_OFIOCGETNEXT;
1323extern unsigned IOCTL_OFIOCGETCHILD;
1324extern unsigned IOCTL_OFIOCFINDDEVICE;
1325extern unsigned IOCTL_AMR_IO_VERSION;
1326extern unsigned IOCTL_AMR_IO_COMMAND;
1327extern unsigned IOCTL_MLYIO_COMMAND;
1328extern unsigned IOCTL_MLYIO_HEALTH;
1329extern unsigned IOCTL_PCI_IOC_CFGREAD;
1330extern unsigned IOCTL_PCI_IOC_CFGWRITE;
1331extern unsigned IOCTL_PCI_IOC_BDF_CFGREAD;
1332extern unsigned IOCTL_PCI_IOC_BDF_CFGWRITE;
1333extern unsigned IOCTL_PCI_IOC_BUSINFO;
1334extern unsigned IOCTL_PCI_IOC_DRVNAME;
1335extern unsigned IOCTL_PCI_IOC_DRVNAMEONBUS;
1336extern unsigned IOCTL_TWEIO_COMMAND;
1337extern unsigned IOCTL_TWEIO_STATS;
1338extern unsigned IOCTL_TWEIO_AEN_POLL;
1339extern unsigned IOCTL_TWEIO_AEN_WAIT;
1340extern unsigned IOCTL_TWEIO_SET_PARAM;
1341extern unsigned IOCTL_TWEIO_GET_PARAM;
1342extern unsigned IOCTL_TWEIO_RESET;
1343extern unsigned IOCTL_TWEIO_ADD_UNIT;
1344extern unsigned IOCTL_TWEIO_DEL_UNIT;
1345extern unsigned IOCTL_SIOCSCNWDOMAIN;
1346extern unsigned IOCTL_SIOCGCNWDOMAIN;
1347extern unsigned IOCTL_SIOCSCNWKEY;
1348extern unsigned IOCTL_SIOCGCNWSTATUS;
1349extern unsigned IOCTL_SIOCGCNWSTATS;
1350extern unsigned IOCTL_SIOCGCNWTRAIL;
1351extern unsigned IOCTL_SIOCGRAYSIGLEV;
1352extern unsigned IOCTL_RAIDFRAME_SHUTDOWN;
1353extern unsigned IOCTL_RAIDFRAME_TUR;
1354extern unsigned IOCTL_RAIDFRAME_FAIL_DISK;
1355extern unsigned IOCTL_RAIDFRAME_CHECK_RECON_STATUS;
1356extern unsigned IOCTL_RAIDFRAME_REWRITEPARITY;
1357extern unsigned IOCTL_RAIDFRAME_COPYBACK;
1358extern unsigned IOCTL_RAIDFRAME_SPARET_WAIT;
1359extern unsigned IOCTL_RAIDFRAME_SEND_SPARET;
1360extern unsigned IOCTL_RAIDFRAME_ABORT_SPARET_WAIT;
1361extern unsigned IOCTL_RAIDFRAME_START_ATRACE;
1362extern unsigned IOCTL_RAIDFRAME_STOP_ATRACE;
1363extern unsigned IOCTL_RAIDFRAME_GET_SIZE;
1364extern unsigned IOCTL_RAIDFRAME_RESET_ACCTOTALS;
1365extern unsigned IOCTL_RAIDFRAME_KEEP_ACCTOTALS;
1366extern unsigned IOCTL_RAIDFRAME_GET_COMPONENT_LABEL;
1367extern unsigned IOCTL_RAIDFRAME_SET_COMPONENT_LABEL;
1368extern unsigned IOCTL_RAIDFRAME_INIT_LABELS;
1369extern unsigned IOCTL_RAIDFRAME_ADD_HOT_SPARE;
1370extern unsigned IOCTL_RAIDFRAME_REMOVE_HOT_SPARE;
1371extern unsigned IOCTL_RAIDFRAME_REBUILD_IN_PLACE;
1372extern unsigned IOCTL_RAIDFRAME_CHECK_PARITY;
1373extern unsigned IOCTL_RAIDFRAME_CHECK_PARITYREWRITE_STATUS;
1374extern unsigned IOCTL_RAIDFRAME_CHECK_COPYBACK_STATUS;
1375extern unsigned IOCTL_RAIDFRAME_SET_AUTOCONFIG;
1376extern unsigned IOCTL_RAIDFRAME_SET_ROOT;
1377extern unsigned IOCTL_RAIDFRAME_DELETE_COMPONENT;
1378extern unsigned IOCTL_RAIDFRAME_INCORPORATE_HOT_SPARE;
1379extern unsigned IOCTL_RAIDFRAME_CHECK_RECON_STATUS_EXT;
1380extern unsigned IOCTL_RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT;
1381extern unsigned IOCTL_RAIDFRAME_CHECK_COPYBACK_STATUS_EXT;
1382extern unsigned IOCTL_RAIDFRAME_CONFIGURE;
1383extern unsigned IOCTL_RAIDFRAME_GET_INFO;
1384extern unsigned IOCTL_RAIDFRAME_PARITYMAP_STATUS;
1385extern unsigned IOCTL_RAIDFRAME_PARITYMAP_GET_DISABLE;
1386extern unsigned IOCTL_RAIDFRAME_PARITYMAP_SET_DISABLE;
1387extern unsigned IOCTL_RAIDFRAME_PARITYMAP_SET_PARAMS;
1388extern unsigned IOCTL_RAIDFRAME_SET_LAST_UNIT;
1389extern unsigned IOCTL_MBPPIOCSPARAM;
1390extern unsigned IOCTL_MBPPIOCGPARAM;
1391extern unsigned IOCTL_MBPPIOCGSTAT;
1392extern unsigned IOCTL_SESIOC_GETNOBJ;
1393extern unsigned IOCTL_SESIOC_GETOBJMAP;
1394extern unsigned IOCTL_SESIOC_GETENCSTAT;
1395extern unsigned IOCTL_SESIOC_SETENCSTAT;
1396extern unsigned IOCTL_SESIOC_GETOBJSTAT;
1397extern unsigned IOCTL_SESIOC_SETOBJSTAT;
1398extern unsigned IOCTL_SESIOC_GETTEXT;
1399extern unsigned IOCTL_SESIOC_INIT;
1400extern unsigned IOCTL_SUN_DKIOCGGEOM;
1401extern unsigned IOCTL_SUN_DKIOCINFO;
1402extern unsigned IOCTL_SUN_DKIOCGPART;
1403extern unsigned IOCTL_FBIOGTYPE;
1404extern unsigned IOCTL_FBIOPUTCMAP;
1405extern unsigned IOCTL_FBIOGETCMAP;
1406extern unsigned IOCTL_FBIOGATTR;
1407extern unsigned IOCTL_FBIOSVIDEO;
1408extern unsigned IOCTL_FBIOGVIDEO;
1409extern unsigned IOCTL_FBIOSCURSOR;
1410extern unsigned IOCTL_FBIOGCURSOR;
1411extern unsigned IOCTL_FBIOSCURPOS;
1412extern unsigned IOCTL_FBIOGCURPOS;
1413extern unsigned IOCTL_FBIOGCURMAX;
1414extern unsigned IOCTL_KIOCTRANS;
1415extern unsigned IOCTL_KIOCSETKEY;
1416extern unsigned IOCTL_KIOCGETKEY;
1417extern unsigned IOCTL_KIOCGTRANS;
1418extern unsigned IOCTL_KIOCCMD;
1419extern unsigned IOCTL_KIOCTYPE;
1420extern unsigned IOCTL_KIOCSDIRECT;
1421extern unsigned IOCTL_KIOCSKEY;
1422extern unsigned IOCTL_KIOCGKEY;
1423extern unsigned IOCTL_KIOCSLED;
1424extern unsigned IOCTL_KIOCGLED;
1425extern unsigned IOCTL_KIOCLAYOUT;
1426extern unsigned IOCTL_VUIDSFORMAT;
1427extern unsigned IOCTL_VUIDGFORMAT;
1428extern unsigned IOCTL_STICIO_GXINFO;
1429extern unsigned IOCTL_STICIO_RESET;
1430extern unsigned IOCTL_STICIO_STARTQ;
1431extern unsigned IOCTL_STICIO_STOPQ;
1432extern unsigned IOCTL_UKYOPON_IDENTIFY;
1433extern unsigned IOCTL_URIO_SEND_COMMAND;
1434extern unsigned IOCTL_URIO_RECV_COMMAND;
1435extern unsigned IOCTL_USB_REQUEST;
1436extern unsigned IOCTL_USB_SETDEBUG;
1437extern unsigned IOCTL_USB_DISCOVER;
1438extern unsigned IOCTL_USB_DEVICEINFO;
1439extern unsigned IOCTL_USB_DEVICEINFO_OLD;
1440extern unsigned IOCTL_USB_DEVICESTATS;
1441extern unsigned IOCTL_USB_GET_REPORT_DESC;
1442extern unsigned IOCTL_USB_SET_IMMED;
1443extern unsigned IOCTL_USB_GET_REPORT;
1444extern unsigned IOCTL_USB_SET_REPORT;
1445extern unsigned IOCTL_USB_GET_REPORT_ID;
1446extern unsigned IOCTL_USB_GET_CONFIG;
1447extern unsigned IOCTL_USB_SET_CONFIG;
1448extern unsigned IOCTL_USB_GET_ALTINTERFACE;
1449extern unsigned IOCTL_USB_SET_ALTINTERFACE;
1450extern unsigned IOCTL_USB_GET_NO_ALT;
1451extern unsigned IOCTL_USB_GET_DEVICE_DESC;
1452extern unsigned IOCTL_USB_GET_CONFIG_DESC;
1453extern unsigned IOCTL_USB_GET_INTERFACE_DESC;
1454extern unsigned IOCTL_USB_GET_ENDPOINT_DESC;
1455extern unsigned IOCTL_USB_GET_FULL_DESC;
1456extern unsigned IOCTL_USB_GET_STRING_DESC;
1457extern unsigned IOCTL_USB_DO_REQUEST;
1458extern unsigned IOCTL_USB_GET_DEVICEINFO;
1459extern unsigned IOCTL_USB_GET_DEVICEINFO_OLD;
1460extern unsigned IOCTL_USB_SET_SHORT_XFER;
1461extern unsigned IOCTL_USB_SET_TIMEOUT;
1462extern unsigned IOCTL_USB_SET_BULK_RA;
1463extern unsigned IOCTL_USB_SET_BULK_WB;
1464extern unsigned IOCTL_USB_SET_BULK_RA_OPT;
1465extern unsigned IOCTL_USB_SET_BULK_WB_OPT;
1466extern unsigned IOCTL_USB_GET_CM_OVER_DATA;
1467extern unsigned IOCTL_USB_SET_CM_OVER_DATA;
1468extern unsigned IOCTL_UTOPPYIOTURBO;
1469extern unsigned IOCTL_UTOPPYIOCANCEL;
1470extern unsigned IOCTL_UTOPPYIOREBOOT;
1471extern unsigned IOCTL_UTOPPYIOSTATS;
1472extern unsigned IOCTL_UTOPPYIORENAME;
1473extern unsigned IOCTL_UTOPPYIOMKDIR;
1474extern unsigned IOCTL_UTOPPYIODELETE;
1475extern unsigned IOCTL_UTOPPYIOREADDIR;
1476extern unsigned IOCTL_UTOPPYIOREADFILE;
1477extern unsigned IOCTL_UTOPPYIOWRITEFILE;
1478extern unsigned IOCTL_DIOSXDCMD;
1479extern unsigned IOCTL_VT_OPENQRY;
1480extern unsigned IOCTL_VT_SETMODE;
1481extern unsigned IOCTL_VT_GETMODE;
1482extern unsigned IOCTL_VT_RELDISP;
1483extern unsigned IOCTL_VT_ACTIVATE;
1484extern unsigned IOCTL_VT_WAITACTIVE;
1485extern unsigned IOCTL_VT_GETACTIVE;
1486extern unsigned IOCTL_VT_GETSTATE;
1487extern unsigned IOCTL_KDGETKBENT;
1488extern unsigned IOCTL_KDGKBMODE;
1489extern unsigned IOCTL_KDSKBMODE;
1490extern unsigned IOCTL_KDMKTONE;
1491extern unsigned IOCTL_KDSETMODE;
1492extern unsigned IOCTL_KDENABIO;
1493extern unsigned IOCTL_KDDISABIO;
1494extern unsigned IOCTL_KDGKBTYPE;
1495extern unsigned IOCTL_KDGETLED;
1496extern unsigned IOCTL_KDSETLED;
1497extern unsigned IOCTL_KDSETRAD;
1498extern unsigned IOCTL_VGAPCVTID;
1499extern unsigned IOCTL_CONS_GETVERS;
1500extern unsigned IOCTL_WSKBDIO_GTYPE;
1501extern unsigned IOCTL_WSKBDIO_BELL;
1502extern unsigned IOCTL_WSKBDIO_COMPLEXBELL;
1503extern unsigned IOCTL_WSKBDIO_SETBELL;
1504extern unsigned IOCTL_WSKBDIO_GETBELL;
1505extern unsigned IOCTL_WSKBDIO_SETDEFAULTBELL;
1506extern unsigned IOCTL_WSKBDIO_GETDEFAULTBELL;
1507extern unsigned IOCTL_WSKBDIO_SETKEYREPEAT;
1508extern unsigned IOCTL_WSKBDIO_GETKEYREPEAT;
1509extern unsigned IOCTL_WSKBDIO_SETDEFAULTKEYREPEAT;
1510extern unsigned IOCTL_WSKBDIO_GETDEFAULTKEYREPEAT;
1511extern unsigned IOCTL_WSKBDIO_SETLEDS;
1512extern unsigned IOCTL_WSKBDIO_GETLEDS;
1513extern unsigned IOCTL_WSKBDIO_GETMAP;
1514extern unsigned IOCTL_WSKBDIO_SETMAP;
1515extern unsigned IOCTL_WSKBDIO_GETENCODING;
1516extern unsigned IOCTL_WSKBDIO_SETENCODING;
1517extern unsigned IOCTL_WSKBDIO_SETMODE;
1518extern unsigned IOCTL_WSKBDIO_GETMODE;
1519extern unsigned IOCTL_WSKBDIO_SETKEYCLICK;
1520extern unsigned IOCTL_WSKBDIO_GETKEYCLICK;
1521extern unsigned IOCTL_WSKBDIO_GETSCROLL;
1522extern unsigned IOCTL_WSKBDIO_SETSCROLL;
1523extern unsigned IOCTL_WSKBDIO_SETVERSION;
1524extern unsigned IOCTL_WSMOUSEIO_GTYPE;
1525extern unsigned IOCTL_WSMOUSEIO_SRES;
1526extern unsigned IOCTL_WSMOUSEIO_SSCALE;
1527extern unsigned IOCTL_WSMOUSEIO_SRATE;
1528extern unsigned IOCTL_WSMOUSEIO_SCALIBCOORDS;
1529extern unsigned IOCTL_WSMOUSEIO_GCALIBCOORDS;
1530extern unsigned IOCTL_WSMOUSEIO_GETID;
1531extern unsigned IOCTL_WSMOUSEIO_GETREPEAT;
1532extern unsigned IOCTL_WSMOUSEIO_SETREPEAT;
1533extern unsigned IOCTL_WSMOUSEIO_SETVERSION;
1534extern unsigned IOCTL_WSDISPLAYIO_GTYPE;
1535extern unsigned IOCTL_WSDISPLAYIO_GINFO;
1536extern unsigned IOCTL_WSDISPLAYIO_GETCMAP;
1537extern unsigned IOCTL_WSDISPLAYIO_PUTCMAP;
1538extern unsigned IOCTL_WSDISPLAYIO_GVIDEO;
1539extern unsigned IOCTL_WSDISPLAYIO_SVIDEO;
1540extern unsigned IOCTL_WSDISPLAYIO_GCURPOS;
1541extern unsigned IOCTL_WSDISPLAYIO_SCURPOS;
1542extern unsigned IOCTL_WSDISPLAYIO_GCURMAX;
1543extern unsigned IOCTL_WSDISPLAYIO_GCURSOR;
1544extern unsigned IOCTL_WSDISPLAYIO_SCURSOR;
1545extern unsigned IOCTL_WSDISPLAYIO_GMODE;
1546extern unsigned IOCTL_WSDISPLAYIO_SMODE;
1547extern unsigned IOCTL_WSDISPLAYIO_LDFONT;
1548extern unsigned IOCTL_WSDISPLAYIO_ADDSCREEN;
1549extern unsigned IOCTL_WSDISPLAYIO_DELSCREEN;
1550extern unsigned IOCTL_WSDISPLAYIO_SFONT;
1551extern unsigned IOCTL__O_WSDISPLAYIO_SETKEYBOARD;
1552extern unsigned IOCTL_WSDISPLAYIO_GETPARAM;
1553extern unsigned IOCTL_WSDISPLAYIO_SETPARAM;
1554extern unsigned IOCTL_WSDISPLAYIO_GETACTIVESCREEN;
1555extern unsigned IOCTL_WSDISPLAYIO_GETWSCHAR;
1556extern unsigned IOCTL_WSDISPLAYIO_PUTWSCHAR;
1557extern unsigned IOCTL_WSDISPLAYIO_DGSCROLL;
1558extern unsigned IOCTL_WSDISPLAYIO_DSSCROLL;
1559extern unsigned IOCTL_WSDISPLAYIO_GMSGATTRS;
1560extern unsigned IOCTL_WSDISPLAYIO_SMSGATTRS;
1561extern unsigned IOCTL_WSDISPLAYIO_GBORDER;
1562extern unsigned IOCTL_WSDISPLAYIO_SBORDER;
1563extern unsigned IOCTL_WSDISPLAYIO_SSPLASH;
1564extern unsigned IOCTL_WSDISPLAYIO_SPROGRESS;
1565extern unsigned IOCTL_WSDISPLAYIO_LINEBYTES;
1566extern unsigned IOCTL_WSDISPLAYIO_SETVERSION;
1567extern unsigned IOCTL_WSMUXIO_ADD_DEVICE;
1568extern unsigned IOCTL_WSMUXIO_REMOVE_DEVICE;
1569extern unsigned IOCTL_WSMUXIO_LIST_DEVICES;
1570extern unsigned IOCTL_WSMUXIO_INJECTEVENT;
1571extern unsigned IOCTL_WSDISPLAYIO_GET_BUSID;
1572extern unsigned IOCTL_WSDISPLAYIO_GET_EDID;
1573extern unsigned IOCTL_WSDISPLAYIO_SET_POLLING;
1574extern unsigned IOCTL_WSDISPLAYIO_GET_FBINFO;
1575extern unsigned IOCTL_WSDISPLAYIO_DOBLIT;
1576extern unsigned IOCTL_WSDISPLAYIO_WAITBLIT;
1577extern unsigned IOCTL_BIOCLOCATE;
1578extern unsigned IOCTL_BIOCINQ;
1579extern unsigned IOCTL_BIOCDISK_NOVOL;
1580extern unsigned IOCTL_BIOCDISK;
1581extern unsigned IOCTL_BIOCVOL;
1582extern unsigned IOCTL_BIOCALARM;
1583extern unsigned IOCTL_BIOCBLINK;
1584extern unsigned IOCTL_BIOCSETSTATE;
1585extern unsigned IOCTL_BIOCVOLOPS;
1586extern unsigned IOCTL_MD_GETCONF;
1587extern unsigned IOCTL_MD_SETCONF;
1588extern unsigned IOCTL_CCDIOCSET;
1589extern unsigned IOCTL_CCDIOCCLR;
1590extern unsigned IOCTL_CGDIOCSET;
1591extern unsigned IOCTL_CGDIOCCLR;
1592extern unsigned IOCTL_CGDIOCGET;
1593extern unsigned IOCTL_FSSIOCSET;
1594extern unsigned IOCTL_FSSIOCGET;
1595extern unsigned IOCTL_FSSIOCCLR;
1596extern unsigned IOCTL_FSSIOFSET;
1597extern unsigned IOCTL_FSSIOFGET;
1598extern unsigned IOCTL_BTDEV_ATTACH;
1599extern unsigned IOCTL_BTDEV_DETACH;
1600extern unsigned IOCTL_BTSCO_GETINFO;
1601extern unsigned IOCTL_KTTCP_IO_SEND;
1602extern unsigned IOCTL_KTTCP_IO_RECV;
1603extern unsigned IOCTL_IOC_LOCKSTAT_GVERSION;
1604extern unsigned IOCTL_IOC_LOCKSTAT_ENABLE;
1605extern unsigned IOCTL_IOC_LOCKSTAT_DISABLE;
1606extern unsigned IOCTL_VNDIOCSET;
1607extern unsigned IOCTL_VNDIOCCLR;
1608extern unsigned IOCTL_VNDIOCGET;
1609extern unsigned IOCTL_SPKRTONE;
1610extern unsigned IOCTL_SPKRTUNE;
1611extern unsigned IOCTL_SPKRGETVOL;
1612extern unsigned IOCTL_SPKRSETVOL;
1613#if defined(__x86_64__)
1614extern unsigned IOCTL_NVMM_IOC_CAPABILITY;
1615extern unsigned IOCTL_NVMM_IOC_MACHINE_CREATE;
1616extern unsigned IOCTL_NVMM_IOC_MACHINE_DESTROY;
1617extern unsigned IOCTL_NVMM_IOC_MACHINE_CONFIGURE;
1618extern unsigned IOCTL_NVMM_IOC_VCPU_CREATE;
1619extern unsigned IOCTL_NVMM_IOC_VCPU_DESTROY;
1620extern unsigned IOCTL_NVMM_IOC_VCPU_CONFIGURE;
1621extern unsigned IOCTL_NVMM_IOC_VCPU_SETSTATE;
1622extern unsigned IOCTL_NVMM_IOC_VCPU_GETSTATE;
1623extern unsigned IOCTL_NVMM_IOC_VCPU_INJECT;
1624extern unsigned IOCTL_NVMM_IOC_VCPU_RUN;
1625extern unsigned IOCTL_NVMM_IOC_GPA_MAP;
1626extern unsigned IOCTL_NVMM_IOC_GPA_UNMAP;
1627extern unsigned IOCTL_NVMM_IOC_HVA_MAP;
1628extern unsigned IOCTL_NVMM_IOC_HVA_UNMAP;
1629extern unsigned IOCTL_NVMM_IOC_CTL;
1630#endif
1631extern unsigned IOCTL_AUTOFSREQUEST;
1632extern unsigned IOCTL_AUTOFSDONE;
1633extern unsigned IOCTL_BIOCGBLEN;
1634extern unsigned IOCTL_BIOCSBLEN;
1635extern unsigned IOCTL_BIOCSETF;
1636extern unsigned IOCTL_BIOCFLUSH;
1637extern unsigned IOCTL_BIOCPROMISC;
1638extern unsigned IOCTL_BIOCGDLT;
1639extern unsigned IOCTL_BIOCGETIF;
1640extern unsigned IOCTL_BIOCSETIF;
1641extern unsigned IOCTL_BIOCGSTATS;
1642extern unsigned IOCTL_BIOCGSTATSOLD;
1643extern unsigned IOCTL_BIOCIMMEDIATE;
1644extern unsigned IOCTL_BIOCVERSION;
1645extern unsigned IOCTL_BIOCSTCPF;
1646extern unsigned IOCTL_BIOCSUDPF;
1647extern unsigned IOCTL_BIOCGHDRCMPLT;
1648extern unsigned IOCTL_BIOCSHDRCMPLT;
1649extern unsigned IOCTL_BIOCSDLT;
1650extern unsigned IOCTL_BIOCGDLTLIST;
1651extern unsigned IOCTL_BIOCGDIRECTION;
1652extern unsigned IOCTL_BIOCSDIRECTION;
1653extern unsigned IOCTL_BIOCSRTIMEOUT;
1654extern unsigned IOCTL_BIOCGRTIMEOUT;
1655extern unsigned IOCTL_BIOCGFEEDBACK;
1656extern unsigned IOCTL_BIOCSFEEDBACK;
1657extern unsigned IOCTL_GRESADDRS;
1658extern unsigned IOCTL_GRESADDRD;
1659extern unsigned IOCTL_GREGADDRS;
1660extern unsigned IOCTL_GREGADDRD;
1661extern unsigned IOCTL_GRESPROTO;
1662extern unsigned IOCTL_GREGPROTO;
1663extern unsigned IOCTL_GRESSOCK;
1664extern unsigned IOCTL_GREDSOCK;
1665extern unsigned IOCTL_PPPIOCGRAWIN;
1666extern unsigned IOCTL_PPPIOCGFLAGS;
1667extern unsigned IOCTL_PPPIOCSFLAGS;
1668extern unsigned IOCTL_PPPIOCGASYNCMAP;
1669extern unsigned IOCTL_PPPIOCSASYNCMAP;
1670extern unsigned IOCTL_PPPIOCGUNIT;
1671extern unsigned IOCTL_PPPIOCGRASYNCMAP;
1672extern unsigned IOCTL_PPPIOCSRASYNCMAP;
1673extern unsigned IOCTL_PPPIOCGMRU;
1674extern unsigned IOCTL_PPPIOCSMRU;
1675extern unsigned IOCTL_PPPIOCSMAXCID;
1676extern unsigned IOCTL_PPPIOCGXASYNCMAP;
1677extern unsigned IOCTL_PPPIOCSXASYNCMAP;
1678extern unsigned IOCTL_PPPIOCXFERUNIT;
1679extern unsigned IOCTL_PPPIOCSCOMPRESS;
1680extern unsigned IOCTL_PPPIOCGNPMODE;
1681extern unsigned IOCTL_PPPIOCSNPMODE;
1682extern unsigned IOCTL_PPPIOCGIDLE;
1683extern unsigned IOCTL_PPPIOCGMTU;
1684extern unsigned IOCTL_PPPIOCSMTU;
1685extern unsigned IOCTL_SIOCGPPPSTATS;
1686extern unsigned IOCTL_SIOCGPPPCSTATS;
1687extern unsigned IOCTL_IOC_NPF_VERSION;
1688extern unsigned IOCTL_IOC_NPF_SWITCH;
1689extern unsigned IOCTL_IOC_NPF_LOAD;
1690extern unsigned IOCTL_IOC_NPF_TABLE;
1691extern unsigned IOCTL_IOC_NPF_STATS;
1692extern unsigned IOCTL_IOC_NPF_SAVE;
1693extern unsigned IOCTL_IOC_NPF_RULE;
1694extern unsigned IOCTL_IOC_NPF_CONN_LOOKUP;
1695extern unsigned IOCTL_IOC_NPF_TABLE_REPLACE;
1696extern unsigned IOCTL_PPPOESETPARMS;
1697extern unsigned IOCTL_PPPOEGETPARMS;
1698extern unsigned IOCTL_PPPOEGETSESSION;
1699extern unsigned IOCTL_SPPPGETAUTHCFG;
1700extern unsigned IOCTL_SPPPSETAUTHCFG;
1701extern unsigned IOCTL_SPPPGETLCPCFG;
1702extern unsigned IOCTL_SPPPSETLCPCFG;
1703extern unsigned IOCTL_SPPPGETSTATUS;
1704extern unsigned IOCTL_SPPPGETSTATUSNCP;
1705extern unsigned IOCTL_SPPPGETIDLETO;
1706extern unsigned IOCTL_SPPPSETIDLETO;
1707extern unsigned IOCTL_SPPPGETAUTHFAILURES;
1708extern unsigned IOCTL_SPPPSETAUTHFAILURE;
1709extern unsigned IOCTL_SPPPSETDNSOPTS;
1710extern unsigned IOCTL_SPPPGETDNSOPTS;
1711extern unsigned IOCTL_SPPPGETDNSADDRS;
1712extern unsigned IOCTL_SPPPSETKEEPALIVE;
1713extern unsigned IOCTL_SPPPGETKEEPALIVE;
1714extern unsigned IOCTL_SRT_GETNRT;
1715extern unsigned IOCTL_SRT_GETRT;
1716extern unsigned IOCTL_SRT_SETRT;
1717extern unsigned IOCTL_SRT_DELRT;
1718extern unsigned IOCTL_SRT_SFLAGS;
1719extern unsigned IOCTL_SRT_GFLAGS;
1720extern unsigned IOCTL_SRT_SGFLAGS;
1721extern unsigned IOCTL_SRT_DEBUG;
1722extern unsigned IOCTL_TAPGIFNAME;
1723extern unsigned IOCTL_TUNSDEBUG;
1724extern unsigned IOCTL_TUNGDEBUG;
1725extern unsigned IOCTL_TUNSIFMODE;
1726extern unsigned IOCTL_TUNSLMODE;
1727extern unsigned IOCTL_TUNSIFHEAD;
1728extern unsigned IOCTL_TUNGIFHEAD;
1729extern unsigned IOCTL_DIOCSTART;
1730extern unsigned IOCTL_DIOCSTOP;
1731extern unsigned IOCTL_DIOCADDRULE;
1732extern unsigned IOCTL_DIOCGETRULES;
1733extern unsigned IOCTL_DIOCGETRULE;
1734extern unsigned IOCTL_DIOCSETLCK;
1735extern unsigned IOCTL_DIOCCLRSTATES;
1736extern unsigned IOCTL_DIOCGETSTATE;
1737extern unsigned IOCTL_DIOCSETSTATUSIF;
1738extern unsigned IOCTL_DIOCGETSTATUS;
1739extern unsigned IOCTL_DIOCCLRSTATUS;
1740extern unsigned IOCTL_DIOCNATLOOK;
1741extern unsigned IOCTL_DIOCSETDEBUG;
1742extern unsigned IOCTL_DIOCGETSTATES;
1743extern unsigned IOCTL_DIOCCHANGERULE;
1744extern unsigned IOCTL_DIOCSETTIMEOUT;
1745extern unsigned IOCTL_DIOCGETTIMEOUT;
1746extern unsigned IOCTL_DIOCADDSTATE;
1747extern unsigned IOCTL_DIOCCLRRULECTRS;
1748extern unsigned IOCTL_DIOCGETLIMIT;
1749extern unsigned IOCTL_DIOCSETLIMIT;
1750extern unsigned IOCTL_DIOCKILLSTATES;
1751extern unsigned IOCTL_DIOCSTARTALTQ;
1752extern unsigned IOCTL_DIOCSTOPALTQ;
1753extern unsigned IOCTL_DIOCADDALTQ;
1754extern unsigned IOCTL_DIOCGETALTQS;
1755extern unsigned IOCTL_DIOCGETALTQ;
1756extern unsigned IOCTL_DIOCCHANGEALTQ;
1757extern unsigned IOCTL_DIOCGETQSTATS;
1758extern unsigned IOCTL_DIOCBEGINADDRS;
1759extern unsigned IOCTL_DIOCADDADDR;
1760extern unsigned IOCTL_DIOCGETADDRS;
1761extern unsigned IOCTL_DIOCGETADDR;
1762extern unsigned IOCTL_DIOCCHANGEADDR;
1763extern unsigned IOCTL_DIOCADDSTATES;
1764extern unsigned IOCTL_DIOCGETRULESETS;
1765extern unsigned IOCTL_DIOCGETRULESET;
1766extern unsigned IOCTL_DIOCRCLRTABLES;
1767extern unsigned IOCTL_DIOCRADDTABLES;
1768extern unsigned IOCTL_DIOCRDELTABLES;
1769extern unsigned IOCTL_DIOCRGETTABLES;
1770extern unsigned IOCTL_DIOCRGETTSTATS;
1771extern unsigned IOCTL_DIOCRCLRTSTATS;
1772extern unsigned IOCTL_DIOCRCLRADDRS;
1773extern unsigned IOCTL_DIOCRADDADDRS;
1774extern unsigned IOCTL_DIOCRDELADDRS;
1775extern unsigned IOCTL_DIOCRSETADDRS;
1776extern unsigned IOCTL_DIOCRGETADDRS;
1777extern unsigned IOCTL_DIOCRGETASTATS;
1778extern unsigned IOCTL_DIOCRCLRASTATS;
1779extern unsigned IOCTL_DIOCRTSTADDRS;
1780extern unsigned IOCTL_DIOCRSETTFLAGS;
1781extern unsigned IOCTL_DIOCRINADEFINE;
1782extern unsigned IOCTL_DIOCOSFPFLUSH;
1783extern unsigned IOCTL_DIOCOSFPADD;
1784extern unsigned IOCTL_DIOCOSFPGET;
1785extern unsigned IOCTL_DIOCXBEGIN;
1786extern unsigned IOCTL_DIOCXCOMMIT;
1787extern unsigned IOCTL_DIOCXROLLBACK;
1788extern unsigned IOCTL_DIOCGETSRCNODES;
1789extern unsigned IOCTL_DIOCCLRSRCNODES;
1790extern unsigned IOCTL_DIOCSETHOSTID;
1791extern unsigned IOCTL_DIOCIGETIFACES;
1792extern unsigned IOCTL_DIOCSETIFFLAG;
1793extern unsigned IOCTL_DIOCCLRIFFLAG;
1794extern unsigned IOCTL_DIOCKILLSRCNODES;
1795extern unsigned IOCTL_SLIOCGUNIT;
1796extern unsigned IOCTL_SIOCGBTINFO;
1797extern unsigned IOCTL_SIOCGBTINFOA;
1798extern unsigned IOCTL_SIOCNBTINFO;
1799extern unsigned IOCTL_SIOCSBTFLAGS;
1800extern unsigned IOCTL_SIOCSBTPOLICY;
1801extern unsigned IOCTL_SIOCSBTPTYPE;
1802extern unsigned IOCTL_SIOCGBTSTATS;
1803extern unsigned IOCTL_SIOCZBTSTATS;
1804extern unsigned IOCTL_SIOCBTDUMP;
1805extern unsigned IOCTL_SIOCSBTSCOMTU;
1806extern unsigned IOCTL_SIOCGBTFEAT;
1807extern unsigned IOCTL_SIOCADNAT;
1808extern unsigned IOCTL_SIOCRMNAT;
1809extern unsigned IOCTL_SIOCGNATS;
1810extern unsigned IOCTL_SIOCGNATL;
1811extern unsigned IOCTL_SIOCPURGENAT;
1812extern unsigned IOCTL_SIOCCONNECTX;
1813extern unsigned IOCTL_SIOCCONNECTXDEL;
1814extern unsigned IOCTL_SIOCSIFINFO_FLAGS;
1815extern unsigned IOCTL_SIOCAADDRCTL_POLICY;
1816extern unsigned IOCTL_SIOCDADDRCTL_POLICY;
1817extern unsigned IOCTL_SMBIOC_OPENSESSION;
1818extern unsigned IOCTL_SMBIOC_OPENSHARE;
1819extern unsigned IOCTL_SMBIOC_REQUEST;
1820extern unsigned IOCTL_SMBIOC_SETFLAGS;
1821extern unsigned IOCTL_SMBIOC_LOOKUP;
1822extern unsigned IOCTL_SMBIOC_READ;
1823extern unsigned IOCTL_SMBIOC_WRITE;
1824extern unsigned IOCTL_AGPIOC_INFO;
1825extern unsigned IOCTL_AGPIOC_ACQUIRE;
1826extern unsigned IOCTL_AGPIOC_RELEASE;
1827extern unsigned IOCTL_AGPIOC_SETUP;
1828extern unsigned IOCTL_AGPIOC_ALLOCATE;
1829extern unsigned IOCTL_AGPIOC_DEALLOCATE;
1830extern unsigned IOCTL_AGPIOC_BIND;
1831extern unsigned IOCTL_AGPIOC_UNBIND;
1832extern unsigned IOCTL_AUDIO_GETINFO;
1833extern unsigned IOCTL_AUDIO_SETINFO;
1834extern unsigned IOCTL_AUDIO_DRAIN;
1835extern unsigned IOCTL_AUDIO_FLUSH;
1836extern unsigned IOCTL_AUDIO_WSEEK;
1837extern unsigned IOCTL_AUDIO_RERROR;
1838extern unsigned IOCTL_AUDIO_GETDEV;
1839extern unsigned IOCTL_AUDIO_GETENC;
1840extern unsigned IOCTL_AUDIO_GETFD;
1841extern unsigned IOCTL_AUDIO_SETFD;
1842extern unsigned IOCTL_AUDIO_PERROR;
1843extern unsigned IOCTL_AUDIO_GETIOFFS;
1844extern unsigned IOCTL_AUDIO_GETOOFFS;
1845extern unsigned IOCTL_AUDIO_GETPROPS;
1846extern unsigned IOCTL_AUDIO_GETBUFINFO;
1847extern unsigned IOCTL_AUDIO_SETCHAN;
1848extern unsigned IOCTL_AUDIO_GETCHAN;
1849extern unsigned IOCTL_AUDIO_QUERYFORMAT;
1850extern unsigned IOCTL_AUDIO_GETFORMAT;
1851extern unsigned IOCTL_AUDIO_SETFORMAT;
1852extern unsigned IOCTL_AUDIO_MIXER_READ;
1853extern unsigned IOCTL_AUDIO_MIXER_WRITE;
1854extern unsigned IOCTL_AUDIO_MIXER_DEVINFO;
1855extern unsigned IOCTL_ATAIOCCOMMAND;
1856extern unsigned IOCTL_ATABUSIOSCAN;
1857extern unsigned IOCTL_ATABUSIORESET;
1858extern unsigned IOCTL_ATABUSIODETACH;
1859extern unsigned IOCTL_CDIOCPLAYTRACKS;
1860extern unsigned IOCTL_CDIOCPLAYBLOCKS;
1861extern unsigned IOCTL_CDIOCREADSUBCHANNEL;
1862extern unsigned IOCTL_CDIOREADTOCHEADER;
1863extern unsigned IOCTL_CDIOREADTOCENTRIES;
1864extern unsigned IOCTL_CDIOREADMSADDR;
1865extern unsigned IOCTL_CDIOCSETPATCH;
1866extern unsigned IOCTL_CDIOCGETVOL;
1867extern unsigned IOCTL_CDIOCSETVOL;
1868extern unsigned IOCTL_CDIOCSETMONO;
1869extern unsigned IOCTL_CDIOCSETSTEREO;
1870extern unsigned IOCTL_CDIOCSETMUTE;
1871extern unsigned IOCTL_CDIOCSETLEFT;
1872extern unsigned IOCTL_CDIOCSETRIGHT;
1873extern unsigned IOCTL_CDIOCSETDEBUG;
1874extern unsigned IOCTL_CDIOCCLRDEBUG;
1875extern unsigned IOCTL_CDIOCPAUSE;
1876extern unsigned IOCTL_CDIOCRESUME;
1877extern unsigned IOCTL_CDIOCRESET;
1878extern unsigned IOCTL_CDIOCSTART;
1879extern unsigned IOCTL_CDIOCSTOP;
1880extern unsigned IOCTL_CDIOCEJECT;
1881extern unsigned IOCTL_CDIOCALLOW;
1882extern unsigned IOCTL_CDIOCPREVENT;
1883extern unsigned IOCTL_CDIOCCLOSE;
1884extern unsigned IOCTL_CDIOCPLAYMSF;
1885extern unsigned IOCTL_CDIOCLOADUNLOAD;
1886extern unsigned IOCTL_CHIOMOVE;
1887extern unsigned IOCTL_CHIOEXCHANGE;
1888extern unsigned IOCTL_CHIOPOSITION;
1889extern unsigned IOCTL_CHIOGPICKER;
1890extern unsigned IOCTL_CHIOSPICKER;
1891extern unsigned IOCTL_CHIOGPARAMS;
1892extern unsigned IOCTL_CHIOIELEM;
1893extern unsigned IOCTL_OCHIOGSTATUS;
1894extern unsigned IOCTL_CHIOGSTATUS;
1895extern unsigned IOCTL_CHIOSVOLTAG;
1896extern unsigned IOCTL_CLOCKCTL_SETTIMEOFDAY;
1897extern unsigned IOCTL_CLOCKCTL_ADJTIME;
1898extern unsigned IOCTL_CLOCKCTL_CLOCK_SETTIME;
1899extern unsigned IOCTL_CLOCKCTL_NTP_ADJTIME;
1900extern unsigned IOCTL_IOC_CPU_SETSTATE;
1901extern unsigned IOCTL_IOC_CPU_GETSTATE;
1902extern unsigned IOCTL_IOC_CPU_GETCOUNT;
1903extern unsigned IOCTL_IOC_CPU_MAPID;
1904extern unsigned IOCTL_IOC_CPU_UCODE_GET_VERSION;
1905extern unsigned IOCTL_IOC_CPU_UCODE_APPLY;
1906extern unsigned IOCTL_DIOCGDINFO;
1907extern unsigned IOCTL_DIOCSDINFO;
1908extern unsigned IOCTL_DIOCWDINFO;
1909extern unsigned IOCTL_DIOCRFORMAT;
1910extern unsigned IOCTL_DIOCWFORMAT;
1911extern unsigned IOCTL_DIOCSSTEP;
1912extern unsigned IOCTL_DIOCSRETRIES;
1913extern unsigned IOCTL_DIOCKLABEL;
1914extern unsigned IOCTL_DIOCWLABEL;
1915extern unsigned IOCTL_DIOCSBAD;
1916extern unsigned IOCTL_DIOCEJECT;
1917extern unsigned IOCTL_ODIOCEJECT;
1918extern unsigned IOCTL_DIOCLOCK;
1919extern unsigned IOCTL_DIOCGDEFLABEL;
1920extern unsigned IOCTL_DIOCCLRLABEL;
1921extern unsigned IOCTL_DIOCGCACHE;
1922extern unsigned IOCTL_DIOCSCACHE;
1923extern unsigned IOCTL_DIOCCACHESYNC;
1924extern unsigned IOCTL_DIOCBSLIST;
1925extern unsigned IOCTL_DIOCBSFLUSH;
1926extern unsigned IOCTL_DIOCAWEDGE;
1927extern unsigned IOCTL_DIOCGWEDGEINFO;
1928extern unsigned IOCTL_DIOCDWEDGE;
1929extern unsigned IOCTL_DIOCLWEDGES;
1930extern unsigned IOCTL_DIOCGSTRATEGY;
1931extern unsigned IOCTL_DIOCSSTRATEGY;
1932extern unsigned IOCTL_DIOCGDISKINFO;
1933extern unsigned IOCTL_DIOCTUR;
1934extern unsigned IOCTL_DIOCMWEDGES;
1935extern unsigned IOCTL_DIOCGSECTORSIZE;
1936extern unsigned IOCTL_DIOCGMEDIASIZE;
1937extern unsigned IOCTL_DIOCRMWEDGES;
1938extern unsigned IOCTL_DRVDETACHDEV;
1939extern unsigned IOCTL_DRVRESCANBUS;
1940extern unsigned IOCTL_DRVCTLCOMMAND;
1941extern unsigned IOCTL_DRVRESUMEDEV;
1942extern unsigned IOCTL_DRVLISTDEV;
1943extern unsigned IOCTL_DRVGETEVENT;
1944extern unsigned IOCTL_DRVSUSPENDDEV;
1945extern unsigned IOCTL_DVD_READ_STRUCT;
1946extern unsigned IOCTL_DVD_WRITE_STRUCT;
1947extern unsigned IOCTL_DVD_AUTH;
1948extern unsigned IOCTL_ENVSYS_GETDICTIONARY;
1949extern unsigned IOCTL_ENVSYS_SETDICTIONARY;
1950extern unsigned IOCTL_ENVSYS_REMOVEPROPS;
1951extern unsigned IOCTL_ENVSYS_GTREDATA;
1952extern unsigned IOCTL_ENVSYS_GTREINFO;
1953extern unsigned IOCTL_KFILTER_BYFILTER;
1954extern unsigned IOCTL_KFILTER_BYNAME;
1955extern unsigned IOCTL_FDIOCGETOPTS;
1956extern unsigned IOCTL_FDIOCSETOPTS;
1957extern unsigned IOCTL_FDIOCSETFORMAT;
1958extern unsigned IOCTL_FDIOCGETFORMAT;
1959extern unsigned IOCTL_FDIOCFORMAT_TRACK;
1960extern unsigned IOCTL_FIOCLEX;
1961extern unsigned IOCTL_FIONCLEX;
1962extern unsigned IOCTL_FIOSEEKDATA;
1963extern unsigned IOCTL_FIOSEEKHOLE;
1964extern unsigned IOCTL_FIONREAD;
1965extern unsigned IOCTL_FIONBIO;
1966extern unsigned IOCTL_FIOASYNC;
1967extern unsigned IOCTL_FIOSETOWN;
1968extern unsigned IOCTL_FIOGETOWN;
1969extern unsigned IOCTL_OFIOGETBMAP;
1970extern unsigned IOCTL_FIOGETBMAP;
1971extern unsigned IOCTL_FIONWRITE;
1972extern unsigned IOCTL_FIONSPACE;
1973extern unsigned IOCTL_GPIOINFO;
1974extern unsigned IOCTL_GPIOSET;
1975extern unsigned IOCTL_GPIOUNSET;
1976extern unsigned IOCTL_GPIOREAD;
1977extern unsigned IOCTL_GPIOWRITE;
1978extern unsigned IOCTL_GPIOTOGGLE;
1979extern unsigned IOCTL_GPIOATTACH;
1980extern unsigned IOCTL_PTIOCNETBSD;
1981extern unsigned IOCTL_PTIOCSUNOS;
1982extern unsigned IOCTL_PTIOCLINUX;
1983extern unsigned IOCTL_PTIOCFREEBSD;
1984extern unsigned IOCTL_PTIOCULTRIX;
1985extern unsigned IOCTL_TIOCHPCL;
1986extern unsigned IOCTL_TIOCGETP;
1987extern unsigned IOCTL_TIOCSETP;
1988extern unsigned IOCTL_TIOCSETN;
1989extern unsigned IOCTL_TIOCSETC;
1990extern unsigned IOCTL_TIOCGETC;
1991extern unsigned IOCTL_TIOCLBIS;
1992extern unsigned IOCTL_TIOCLBIC;
1993extern unsigned IOCTL_TIOCLSET;
1994extern unsigned IOCTL_TIOCLGET;
1995extern unsigned IOCTL_TIOCSLTC;
1996extern unsigned IOCTL_TIOCGLTC;
1997extern unsigned IOCTL_OTIOCCONS;
1998extern unsigned IOCTL_JOY_SETTIMEOUT;
1999extern unsigned IOCTL_JOY_GETTIMEOUT;
2000extern unsigned IOCTL_JOY_SET_X_OFFSET;
2001extern unsigned IOCTL_JOY_SET_Y_OFFSET;
2002extern unsigned IOCTL_JOY_GET_X_OFFSET;
2003extern unsigned IOCTL_JOY_GET_Y_OFFSET;
2004extern unsigned IOCTL_OKIOCGSYMBOL;
2005extern unsigned IOCTL_OKIOCGVALUE;
2006extern unsigned IOCTL_KIOCGSIZE;
2007extern unsigned IOCTL_KIOCGVALUE;
2008extern unsigned IOCTL_KIOCGSYMBOL;
2009extern unsigned IOCTL_LUAINFO;
2010extern unsigned IOCTL_LUACREATE;
2011extern unsigned IOCTL_LUADESTROY;
2012extern unsigned IOCTL_LUAREQUIRE;
2013extern unsigned IOCTL_LUALOAD;
2014extern unsigned IOCTL_MIDI_PRETIME;
2015extern unsigned IOCTL_MIDI_MPUMODE;
2016extern unsigned IOCTL_MIDI_MPUCMD;
2017extern unsigned IOCTL_SEQUENCER_RESET;
2018extern unsigned IOCTL_SEQUENCER_SYNC;
2019extern unsigned IOCTL_SEQUENCER_INFO;
2020extern unsigned IOCTL_SEQUENCER_CTRLRATE;
2021extern unsigned IOCTL_SEQUENCER_GETOUTCOUNT;
2022extern unsigned IOCTL_SEQUENCER_GETINCOUNT;
2023extern unsigned IOCTL_SEQUENCER_RESETSAMPLES;
2024extern unsigned IOCTL_SEQUENCER_NRSYNTHS;
2025extern unsigned IOCTL_SEQUENCER_NRMIDIS;
2026extern unsigned IOCTL_SEQUENCER_THRESHOLD;
2027extern unsigned IOCTL_SEQUENCER_MEMAVL;
2028extern unsigned IOCTL_SEQUENCER_PANIC;
2029extern unsigned IOCTL_SEQUENCER_OUTOFBAND;
2030extern unsigned IOCTL_SEQUENCER_GETTIME;
2031extern unsigned IOCTL_SEQUENCER_TMR_TIMEBASE;
2032extern unsigned IOCTL_SEQUENCER_TMR_START;
2033extern unsigned IOCTL_SEQUENCER_TMR_STOP;
2034extern unsigned IOCTL_SEQUENCER_TMR_CONTINUE;
2035extern unsigned IOCTL_SEQUENCER_TMR_TEMPO;
2036extern unsigned IOCTL_SEQUENCER_TMR_SOURCE;
2037extern unsigned IOCTL_SEQUENCER_TMR_METRONOME;
2038extern unsigned IOCTL_SEQUENCER_TMR_SELECT;
2039extern unsigned IOCTL_SPI_IOCTL_CONFIGURE;
2040extern unsigned IOCTL_SPI_IOCTL_TRANSFER;
2041extern unsigned IOCTL_MTIOCTOP;
2042extern unsigned IOCTL_MTIOCGET;
2043extern unsigned IOCTL_MTIOCIEOT;
2044extern unsigned IOCTL_MTIOCEEOT;
2045extern unsigned IOCTL_MTIOCRDSPOS;
2046extern unsigned IOCTL_MTIOCRDHPOS;
2047extern unsigned IOCTL_MTIOCSLOCATE;
2048extern unsigned IOCTL_MTIOCHLOCATE;
2049extern unsigned IOCTL_POWER_EVENT_RECVDICT;
2050extern unsigned IOCTL_POWER_IOC_GET_TYPE;
2051extern unsigned IOCTL_RIOCGINFO;
2052extern unsigned IOCTL_RIOCSINFO;
2053extern unsigned IOCTL_RIOCSSRCH;
2054extern unsigned IOCTL_RNDGETENTCNT;
2055extern unsigned IOCTL_RNDGETSRCNUM;
2056extern unsigned IOCTL_RNDGETSRCNAME;
2057extern unsigned IOCTL_RNDCTL;
2058extern unsigned IOCTL_RNDADDDATA;
2059extern unsigned IOCTL_RNDGETPOOLSTAT;
2060extern unsigned IOCTL_RNDGETESTNUM;
2061extern unsigned IOCTL_RNDGETESTNAME;
2062extern unsigned IOCTL_SCIOCGET;
2063extern unsigned IOCTL_SCIOCSET;
2064extern unsigned IOCTL_SCIOCRESTART;
2065extern unsigned IOCTL_SCIOC_USE_ADF;
2066extern unsigned IOCTL_SCIOCCOMMAND;
2067extern unsigned IOCTL_SCIOCDEBUG;
2068extern unsigned IOCTL_SCIOCIDENTIFY;
2069extern unsigned IOCTL_OSCIOCIDENTIFY;
2070extern unsigned IOCTL_SCIOCDECONFIG;
2071extern unsigned IOCTL_SCIOCRECONFIG;
2072extern unsigned IOCTL_SCIOCRESET;
2073extern unsigned IOCTL_SCBUSIOSCAN;
2074extern unsigned IOCTL_SCBUSIORESET;
2075extern unsigned IOCTL_SCBUSIODETACH;
2076extern unsigned IOCTL_SCBUSACCEL;
2077extern unsigned IOCTL_SCBUSIOLLSCAN;
2078extern unsigned IOCTL_SIOCSHIWAT;
2079extern unsigned IOCTL_SIOCGHIWAT;
2080extern unsigned IOCTL_SIOCSLOWAT;
2081extern unsigned IOCTL_SIOCGLOWAT;
2082extern unsigned IOCTL_SIOCATMARK;
2083extern unsigned IOCTL_SIOCSPGRP;
2084extern unsigned IOCTL_SIOCGPGRP;
2085extern unsigned IOCTL_SIOCPEELOFF;
2086extern unsigned IOCTL_SIOCADDRT;
2087extern unsigned IOCTL_SIOCDELRT;
2088extern unsigned IOCTL_SIOCSIFADDR;
2089extern unsigned IOCTL_SIOCGIFADDR;
2090extern unsigned IOCTL_SIOCSIFDSTADDR;
2091extern unsigned IOCTL_SIOCGIFDSTADDR;
2092extern unsigned IOCTL_SIOCSIFFLAGS;
2093extern unsigned IOCTL_SIOCGIFFLAGS;
2094extern unsigned IOCTL_SIOCGIFBRDADDR;
2095extern unsigned IOCTL_SIOCSIFBRDADDR;
2096extern unsigned IOCTL_SIOCGIFCONF;
2097extern unsigned IOCTL_SIOCGIFNETMASK;
2098extern unsigned IOCTL_SIOCSIFNETMASK;
2099extern unsigned IOCTL_SIOCGIFMETRIC;
2100extern unsigned IOCTL_SIOCSIFMETRIC;
2101extern unsigned IOCTL_SIOCDIFADDR;
2102extern unsigned IOCTL_SIOCAIFADDR;
2103extern unsigned IOCTL_SIOCGIFALIAS;
2104extern unsigned IOCTL_SIOCGIFAFLAG_IN;
2105extern unsigned IOCTL_SIOCALIFADDR;
2106extern unsigned IOCTL_SIOCGLIFADDR;
2107extern unsigned IOCTL_SIOCDLIFADDR;
2108extern unsigned IOCTL_SIOCSIFADDRPREF;
2109extern unsigned IOCTL_SIOCGIFADDRPREF;
2110extern unsigned IOCTL_SIOCADDMULTI;
2111extern unsigned IOCTL_SIOCDELMULTI;
2112extern unsigned IOCTL_SIOCGETVIFCNT;
2113extern unsigned IOCTL_SIOCGETSGCNT;
2114extern unsigned IOCTL_SIOCSIFMEDIA;
2115extern unsigned IOCTL_SIOCGIFMEDIA;
2116extern unsigned IOCTL_SIOCSIFGENERIC;
2117extern unsigned IOCTL_SIOCGIFGENERIC;
2118extern unsigned IOCTL_SIOCSIFPHYADDR;
2119extern unsigned IOCTL_SIOCGIFPSRCADDR;
2120extern unsigned IOCTL_SIOCGIFPDSTADDR;
2121extern unsigned IOCTL_SIOCDIFPHYADDR;
2122extern unsigned IOCTL_SIOCSLIFPHYADDR;
2123extern unsigned IOCTL_SIOCGLIFPHYADDR;
2124extern unsigned IOCTL_SIOCSIFMTU;
2125extern unsigned IOCTL_SIOCGIFMTU;
2126extern unsigned IOCTL_SIOCSDRVSPEC;
2127extern unsigned IOCTL_SIOCGDRVSPEC;
2128extern unsigned IOCTL_SIOCIFCREATE;
2129extern unsigned IOCTL_SIOCIFDESTROY;
2130extern unsigned IOCTL_SIOCIFGCLONERS;
2131extern unsigned IOCTL_SIOCGIFDLT;
2132extern unsigned IOCTL_SIOCGIFCAP;
2133extern unsigned IOCTL_SIOCSIFCAP;
2134extern unsigned IOCTL_SIOCSVH;
2135extern unsigned IOCTL_SIOCGVH;
2136extern unsigned IOCTL_SIOCINITIFADDR;
2137extern unsigned IOCTL_SIOCGIFDATA;
2138extern unsigned IOCTL_SIOCZIFDATA;
2139extern unsigned IOCTL_SIOCGLINKSTR;
2140extern unsigned IOCTL_SIOCSLINKSTR;
2141extern unsigned IOCTL_SIOCGETHERCAP;
2142extern unsigned IOCTL_SIOCGIFINDEX;
2143extern unsigned IOCTL_SIOCSETHERCAP;
2144extern unsigned IOCTL_SIOCSIFDESCR;
2145extern unsigned IOCTL_SIOCGIFDESCR;
2146extern unsigned IOCTL_SIOCGUMBINFO;
2147extern unsigned IOCTL_SIOCSUMBPARAM;
2148extern unsigned IOCTL_SIOCGUMBPARAM;
2149extern unsigned IOCTL_SIOCSETPFSYNC;
2150extern unsigned IOCTL_SIOCGETPFSYNC;
2151extern unsigned IOCTL_PPS_IOC_CREATE;
2152extern unsigned IOCTL_PPS_IOC_DESTROY;
2153extern unsigned IOCTL_PPS_IOC_SETPARAMS;
2154extern unsigned IOCTL_PPS_IOC_GETPARAMS;
2155extern unsigned IOCTL_PPS_IOC_GETCAP;
2156extern unsigned IOCTL_PPS_IOC_FETCH;
2157extern unsigned IOCTL_PPS_IOC_KCBIND;
2158extern unsigned IOCTL_TIOCEXCL;
2159extern unsigned IOCTL_TIOCNXCL;
2160extern unsigned IOCTL_TIOCFLUSH;
2161extern unsigned IOCTL_TIOCGETA;
2162extern unsigned IOCTL_TIOCSETA;
2163extern unsigned IOCTL_TIOCSETAW;
2164extern unsigned IOCTL_TIOCSETAF;
2165extern unsigned IOCTL_TIOCGETD;
2166extern unsigned IOCTL_TIOCSETD;
2167extern unsigned IOCTL_TIOCGLINED;
2168extern unsigned IOCTL_TIOCSLINED;
2169extern unsigned IOCTL_TIOCSBRK;
2170extern unsigned IOCTL_TIOCCBRK;
2171extern unsigned IOCTL_TIOCSDTR;
2172extern unsigned IOCTL_TIOCCDTR;
2173extern unsigned IOCTL_TIOCGPGRP;
2174extern unsigned IOCTL_TIOCSPGRP;
2175extern unsigned IOCTL_TIOCOUTQ;
2176extern unsigned IOCTL_TIOCSTI;
2177extern unsigned IOCTL_TIOCNOTTY;
2178extern unsigned IOCTL_TIOCPKT;
2179extern unsigned IOCTL_TIOCSTOP;
2180extern unsigned IOCTL_TIOCSTART;
2181extern unsigned IOCTL_TIOCMSET;
2182extern unsigned IOCTL_TIOCMBIS;
2183extern unsigned IOCTL_TIOCMBIC;
2184extern unsigned IOCTL_TIOCMGET;
2185extern unsigned IOCTL_TIOCREMOTE;
2186extern unsigned IOCTL_TIOCGWINSZ;
2187extern unsigned IOCTL_TIOCSWINSZ;
2188extern unsigned IOCTL_TIOCUCNTL;
2189extern unsigned IOCTL_TIOCSTAT;
2190extern unsigned IOCTL_TIOCGSID;
2191extern unsigned IOCTL_TIOCCONS;
2192extern unsigned IOCTL_TIOCSCTTY;
2193extern unsigned IOCTL_TIOCEXT;
2194extern unsigned IOCTL_TIOCSIG;
2195extern unsigned IOCTL_TIOCDRAIN;
2196extern unsigned IOCTL_TIOCGFLAGS;
2197extern unsigned IOCTL_TIOCSFLAGS;
2198extern unsigned IOCTL_TIOCDCDTIMESTAMP;
2199extern unsigned IOCTL_TIOCRCVFRAME;
2200extern unsigned IOCTL_TIOCXMTFRAME;
2201extern unsigned IOCTL_TIOCPTMGET;
2202extern unsigned IOCTL_TIOCGRANTPT;
2203extern unsigned IOCTL_TIOCPTSNAME;
2204extern unsigned IOCTL_TIOCSQSIZE;
2205extern unsigned IOCTL_TIOCGQSIZE;
2206extern unsigned IOCTL_VERIEXEC_LOAD;
2207extern unsigned IOCTL_VERIEXEC_TABLESIZE;
2208extern unsigned IOCTL_VERIEXEC_DELETE;
2209extern unsigned IOCTL_VERIEXEC_QUERY;
2210extern unsigned IOCTL_VERIEXEC_DUMP;
2211extern unsigned IOCTL_VERIEXEC_FLUSH;
2212extern unsigned IOCTL_VIDIOC_QUERYCAP;
2213extern unsigned IOCTL_VIDIOC_RESERVED;
2214extern unsigned IOCTL_VIDIOC_ENUM_FMT;
2215extern unsigned IOCTL_VIDIOC_G_FMT;
2216extern unsigned IOCTL_VIDIOC_S_FMT;
2217extern unsigned IOCTL_VIDIOC_REQBUFS;
2218extern unsigned IOCTL_VIDIOC_QUERYBUF;
2219extern unsigned IOCTL_VIDIOC_G_FBUF;
2220extern unsigned IOCTL_VIDIOC_S_FBUF;
2221extern unsigned IOCTL_VIDIOC_OVERLAY;
2222extern unsigned IOCTL_VIDIOC_QBUF;
2223extern unsigned IOCTL_VIDIOC_DQBUF;
2224extern unsigned IOCTL_VIDIOC_STREAMON;
2225extern unsigned IOCTL_VIDIOC_STREAMOFF;
2226extern unsigned IOCTL_VIDIOC_G_PARM;
2227extern unsigned IOCTL_VIDIOC_S_PARM;
2228extern unsigned IOCTL_VIDIOC_G_STD;
2229extern unsigned IOCTL_VIDIOC_S_STD;
2230extern unsigned IOCTL_VIDIOC_ENUMSTD;
2231extern unsigned IOCTL_VIDIOC_ENUMINPUT;
2232extern unsigned IOCTL_VIDIOC_G_CTRL;
2233extern unsigned IOCTL_VIDIOC_S_CTRL;
2234extern unsigned IOCTL_VIDIOC_G_TUNER;
2235extern unsigned IOCTL_VIDIOC_S_TUNER;
2236extern unsigned IOCTL_VIDIOC_G_AUDIO;
2237extern unsigned IOCTL_VIDIOC_S_AUDIO;
2238extern unsigned IOCTL_VIDIOC_QUERYCTRL;
2239extern unsigned IOCTL_VIDIOC_QUERYMENU;
2240extern unsigned IOCTL_VIDIOC_G_INPUT;
2241extern unsigned IOCTL_VIDIOC_S_INPUT;
2242extern unsigned IOCTL_VIDIOC_G_OUTPUT;
2243extern unsigned IOCTL_VIDIOC_S_OUTPUT;
2244extern unsigned IOCTL_VIDIOC_ENUMOUTPUT;
2245extern unsigned IOCTL_VIDIOC_G_AUDOUT;
2246extern unsigned IOCTL_VIDIOC_S_AUDOUT;
2247extern unsigned IOCTL_VIDIOC_G_MODULATOR;
2248extern unsigned IOCTL_VIDIOC_S_MODULATOR;
2249extern unsigned IOCTL_VIDIOC_G_FREQUENCY;
2250extern unsigned IOCTL_VIDIOC_S_FREQUENCY;
2251extern unsigned IOCTL_VIDIOC_CROPCAP;
2252extern unsigned IOCTL_VIDIOC_G_CROP;
2253extern unsigned IOCTL_VIDIOC_S_CROP;
2254extern unsigned IOCTL_VIDIOC_G_JPEGCOMP;
2255extern unsigned IOCTL_VIDIOC_S_JPEGCOMP;
2256extern unsigned IOCTL_VIDIOC_QUERYSTD;
2257extern unsigned IOCTL_VIDIOC_TRY_FMT;
2258extern unsigned IOCTL_VIDIOC_ENUMAUDIO;
2259extern unsigned IOCTL_VIDIOC_ENUMAUDOUT;
2260extern unsigned IOCTL_VIDIOC_G_PRIORITY;
2261extern unsigned IOCTL_VIDIOC_S_PRIORITY;
2262extern unsigned IOCTL_VIDIOC_ENUM_FRAMESIZES;
2263extern unsigned IOCTL_VIDIOC_ENUM_FRAMEINTERVALS;
2264extern unsigned IOCTL_WDOGIOC_GMODE;
2265extern unsigned IOCTL_WDOGIOC_SMODE;
2266extern unsigned IOCTL_WDOGIOC_WHICH;
2267extern unsigned IOCTL_WDOGIOC_TICKLE;
2268extern unsigned IOCTL_WDOGIOC_GTICKLER;
2269extern unsigned IOCTL_WDOGIOC_GWDOGS;
2270extern unsigned IOCTL_KCOV_IOC_SETBUFSIZE;
2271extern unsigned IOCTL_KCOV_IOC_ENABLE;
2272extern unsigned IOCTL_KCOV_IOC_DISABLE;
2273extern unsigned IOCTL_IPMICTL_RECEIVE_MSG_TRUNC;
2274extern unsigned IOCTL_IPMICTL_RECEIVE_MSG;
2275extern unsigned IOCTL_IPMICTL_SEND_COMMAND;
2276extern unsigned IOCTL_IPMICTL_REGISTER_FOR_CMD;
2277extern unsigned IOCTL_IPMICTL_UNREGISTER_FOR_CMD;
2278extern unsigned IOCTL_IPMICTL_SET_GETS_EVENTS_CMD;
2279extern unsigned IOCTL_IPMICTL_SET_MY_ADDRESS_CMD;
2280extern unsigned IOCTL_IPMICTL_GET_MY_ADDRESS_CMD;
2281extern unsigned IOCTL_IPMICTL_SET_MY_LUN_CMD;
2282extern unsigned IOCTL_IPMICTL_GET_MY_LUN_CMD;
2283extern unsigned IOCTL_SNDCTL_DSP_RESET;
2284extern unsigned IOCTL_SNDCTL_DSP_SYNC;
2285extern unsigned IOCTL_SNDCTL_DSP_SPEED;
2286extern unsigned IOCTL_SOUND_PCM_READ_RATE;
2287extern unsigned IOCTL_SNDCTL_DSP_STEREO;
2288extern unsigned IOCTL_SNDCTL_DSP_GETBLKSIZE;
2289extern unsigned IOCTL_SNDCTL_DSP_SETFMT;
2290extern unsigned IOCTL_SOUND_PCM_READ_BITS;
2291extern unsigned IOCTL_SNDCTL_DSP_CHANNELS;
2292extern unsigned IOCTL_SOUND_PCM_READ_CHANNELS;
2293extern unsigned IOCTL_SOUND_PCM_WRITE_FILTER;
2294extern unsigned IOCTL_SOUND_PCM_READ_FILTER;
2295extern unsigned IOCTL_SNDCTL_DSP_POST;
2296extern unsigned IOCTL_SNDCTL_DSP_SUBDIVIDE;
2297extern unsigned IOCTL_SNDCTL_DSP_SETFRAGMENT;
2298extern unsigned IOCTL_SNDCTL_DSP_GETFMTS;
2299extern unsigned IOCTL_SNDCTL_DSP_GETOSPACE;
2300extern unsigned IOCTL_SNDCTL_DSP_GETISPACE;
2301extern unsigned IOCTL_SNDCTL_DSP_NONBLOCK;
2302extern unsigned IOCTL_SNDCTL_DSP_GETCAPS;
2303extern unsigned IOCTL_SNDCTL_DSP_GETTRIGGER;
2304extern unsigned IOCTL_SNDCTL_DSP_SETTRIGGER;
2305extern unsigned IOCTL_SNDCTL_DSP_GETIPTR;
2306extern unsigned IOCTL_SNDCTL_DSP_GETOPTR;
2307extern unsigned IOCTL_SNDCTL_DSP_MAPINBUF;
2308extern unsigned IOCTL_SNDCTL_DSP_MAPOUTBUF;
2309extern unsigned IOCTL_SNDCTL_DSP_SETSYNCRO;
2310extern unsigned IOCTL_SNDCTL_DSP_SETDUPLEX;
2311extern unsigned IOCTL_SNDCTL_DSP_PROFILE;
2312extern unsigned IOCTL_SNDCTL_DSP_GETODELAY;
2313extern unsigned IOCTL_SOUND_MIXER_INFO;
2314extern unsigned IOCTL_SOUND_OLD_MIXER_INFO;
2315extern unsigned IOCTL_OSS_GETVERSION;
2316extern unsigned IOCTL_SNDCTL_SYSINFO;
2317extern unsigned IOCTL_SNDCTL_AUDIOINFO;
2318extern unsigned IOCTL_SNDCTL_ENGINEINFO;
2319extern unsigned IOCTL_SNDCTL_DSP_GETPLAYVOL;
2320extern unsigned IOCTL_SNDCTL_DSP_SETPLAYVOL;
2321extern unsigned IOCTL_SNDCTL_DSP_GETRECVOL;
2322extern unsigned IOCTL_SNDCTL_DSP_SETRECVOL;
2323extern unsigned IOCTL_SNDCTL_DSP_SKIP;
2324extern unsigned IOCTL_SNDCTL_DSP_SILENCE;
2325
2326extern const int si_SEGV_MAPERR;
2327extern const int si_SEGV_ACCERR;
2328
2329extern const unsigned SHA1_CTX_sz;
2330extern const unsigned SHA1_return_length;
2331
2332extern const unsigned MD4_CTX_sz;
2333extern const unsigned MD4_return_length;
2334
2335extern const unsigned RMD160_CTX_sz;
2336extern const unsigned RMD160_return_length;
2337
2338extern const unsigned MD5_CTX_sz;
2339extern const unsigned MD5_return_length;
2340
2341extern const unsigned fpos_t_sz;
2342
2343extern const unsigned MD2_CTX_sz;
2344extern const unsigned MD2_return_length;
2345
2346#define SHA2_EXTERN(LEN) \
2347 extern const unsigned SHA##LEN##_CTX_sz; \
2348 extern const unsigned SHA##LEN##_return_length; \
2349 extern const unsigned SHA##LEN##_block_length; \
2350 extern const unsigned SHA##LEN##_digest_length
2351
2352SHA2_EXTERN(224);
2353SHA2_EXTERN(256);
2354SHA2_EXTERN(384);
2355SHA2_EXTERN(512);
2356
2357#undef SHA2_EXTERN
2358
2359extern const int unvis_valid;
2360extern const int unvis_validpush;
2361
2362struct __sanitizer_cdbr {
2363 void (*unmap)(void *, void *, uptr);
2364 void *cookie;
2365 u8 *mmap_base;
2366 uptr mmap_size;
2367
2368 u8 *hash_base;
2369 u8 *offset_base;
2370 u8 *data_base;
2371
2372 u32 data_size;
2373 u32 entries;
2374 u32 entries_index;
2375 u32 seed;
2376
2377 u8 offset_size;
2378 u8 index_size;
2379
2380 u32 entries_m;
2381 u32 entries_index_m;
2382 u8 entries_s1, entries_s2;
2383 u8 entries_index_s1, entries_index_s2;
2384};
2385
2386struct __sanitizer_cdbw {
2387 uptr data_counter;
2388 uptr data_allocated;
2389 uptr data_size;
2390 uptr *data_len;
2391 void **data_ptr;
2392 uptr hash_size;
2393 void *hash;
2394 uptr key_counter;
2395};
2396} // namespace __sanitizer
2397
2398#define CHECK_TYPE_SIZE(TYPE) \
2399 COMPILER_CHECK(sizeof(__sanitizer_##TYPE) == sizeof(TYPE))
2400
2401#define CHECK_SIZE_AND_OFFSET(CLASS, MEMBER) \
2402 COMPILER_CHECK(sizeof(((__sanitizer_##CLASS *)NULL)->MEMBER) == \
2403 sizeof(((CLASS *)NULL)->MEMBER)); \
2404 COMPILER_CHECK(offsetof(__sanitizer_##CLASS, MEMBER) == \
2405 offsetof(CLASS, MEMBER))
2406
2407// For sigaction, which is a function and struct at the same time,
2408// and thus requires explicit "struct" in sizeof() expression.
2409#define CHECK_STRUCT_SIZE_AND_OFFSET(CLASS, MEMBER) \
2410 COMPILER_CHECK(sizeof(((struct __sanitizer_##CLASS *)NULL)->MEMBER) == \
2411 sizeof(((struct CLASS *)NULL)->MEMBER)); \
2412 COMPILER_CHECK(offsetof(struct __sanitizer_##CLASS, MEMBER) == \
2413 offsetof(struct CLASS, MEMBER))
2414
2415#define SIGACTION_SYMNAME __sigaction14
2416
2417// Compat with 9.0
2418extern unsigned struct_statvfs90_sz;
2419
2420#endif // SANITIZER_NETBSD
2421
2422#endif
lib/tsan/sanitizer_common/sanitizer_platform_limits_openbsd.cpp created+279
...@@ -0,0 +1,279 @@
1//===-- sanitizer_platform_limits_openbsd.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 Sanitizer common code.
10//
11// Sizes and layouts of platform-specific NetBSD data structures.
12//===----------------------------------------------------------------------===//
13
14#include "sanitizer_platform.h"
15
16#if SANITIZER_OPENBSD
17#include <arpa/inet.h>
18#include <dirent.h>
19#include <glob.h>
20#include <grp.h>
21#include <ifaddrs.h>
22#include <limits.h>
23#include <link_elf.h>
24#include <sys/socket.h>
25#include <net/if.h>
26#include <net/ppp_defs.h>
27#include <net/route.h>
28#include <netdb.h>
29#include <netinet/in.h>
30#include <netinet/ip_mroute.h>
31#include <poll.h>
32#include <pthread.h>
33#include <pwd.h>
34#include <semaphore.h>
35#include <signal.h>
36#include <soundcard.h>
37#include <stddef.h>
38#include <stdint.h>
39#include <sys/filio.h>
40#include <sys/ipc.h>
41#include <sys/mman.h>
42#include <sys/mount.h>
43#include <sys/msg.h>
44#include <sys/mtio.h>
45#include <sys/ptrace.h>
46#include <sys/resource.h>
47#include <sys/shm.h>
48#include <sys/signal.h>
49#include <sys/sockio.h>
50#include <sys/stat.h>
51#include <sys/statvfs.h>
52#include <sys/time.h>
53#include <sys/times.h>
54#include <sys/types.h>
55#include <sys/utsname.h>
56#include <term.h>
57#include <time.h>
58#include <utime.h>
59#include <utmp.h>
60#include <wchar.h>
61
62// Include these after system headers to avoid name clashes and ambiguities.
63#include "sanitizer_internal_defs.h"
64#include "sanitizer_platform_limits_openbsd.h"
65
66namespace __sanitizer {
67unsigned struct_utsname_sz = sizeof(struct utsname);
68unsigned struct_stat_sz = sizeof(struct stat);
69unsigned struct_rusage_sz = sizeof(struct rusage);
70unsigned struct_tm_sz = sizeof(struct tm);
71unsigned struct_passwd_sz = sizeof(struct passwd);
72unsigned struct_group_sz = sizeof(struct group);
73unsigned siginfo_t_sz = sizeof(siginfo_t);
74unsigned struct_sigaction_sz = sizeof(struct sigaction);
75unsigned struct_stack_t_sz = sizeof(stack_t);
76unsigned struct_itimerval_sz = sizeof(struct itimerval);
77unsigned pthread_t_sz = sizeof(pthread_t);
78unsigned pthread_mutex_t_sz = sizeof(pthread_mutex_t);
79unsigned pthread_cond_t_sz = sizeof(pthread_cond_t);
80unsigned pid_t_sz = sizeof(pid_t);
81unsigned timeval_sz = sizeof(timeval);
82unsigned uid_t_sz = sizeof(uid_t);
83unsigned gid_t_sz = sizeof(gid_t);
84unsigned mbstate_t_sz = sizeof(mbstate_t);
85unsigned sigset_t_sz = sizeof(sigset_t);
86unsigned struct_timezone_sz = sizeof(struct timezone);
87unsigned struct_tms_sz = sizeof(struct tms);
88unsigned struct_sched_param_sz = sizeof(struct sched_param);
89unsigned struct_sockaddr_sz = sizeof(struct sockaddr);
90unsigned struct_rlimit_sz = sizeof(struct rlimit);
91unsigned struct_timespec_sz = sizeof(struct timespec);
92unsigned struct_utimbuf_sz = sizeof(struct utimbuf);
93unsigned struct_itimerspec_sz = sizeof(struct itimerspec);
94unsigned struct_msqid_ds_sz = sizeof(struct msqid_ds);
95unsigned struct_statvfs_sz = sizeof(struct statvfs);
96
97const uptr sig_ign = (uptr)SIG_IGN;
98const uptr sig_dfl = (uptr)SIG_DFL;
99const uptr sig_err = (uptr)SIG_ERR;
100const uptr sa_siginfo = (uptr)SA_SIGINFO;
101
102int shmctl_ipc_stat = (int)IPC_STAT;
103
104unsigned struct_utmp_sz = sizeof(struct utmp);
105
106int map_fixed = MAP_FIXED;
107
108int af_inet = (int)AF_INET;
109int af_inet6 = (int)AF_INET6;
110
111uptr __sanitizer_in_addr_sz(int af) {
112 if (af == AF_INET)
113 return sizeof(struct in_addr);
114 else if (af == AF_INET6)
115 return sizeof(struct in6_addr);
116 else
117 return 0;
118}
119
120unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
121
122int glob_nomatch = GLOB_NOMATCH;
123int glob_altdirfunc = GLOB_ALTDIRFUNC;
124
125unsigned path_max = PATH_MAX;
126
127const int si_SEGV_MAPERR = SEGV_MAPERR;
128const int si_SEGV_ACCERR = SEGV_ACCERR;
129} // namespace __sanitizer
130
131using namespace __sanitizer;
132
133COMPILER_CHECK(sizeof(__sanitizer_pthread_attr_t) >= sizeof(pthread_attr_t));
134
135COMPILER_CHECK(sizeof(socklen_t) == sizeof(unsigned));
136CHECK_TYPE_SIZE(pthread_key_t);
137
138CHECK_TYPE_SIZE(dl_phdr_info);
139CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_addr);
140CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_name);
141CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_phdr);
142CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_phnum);
143
144CHECK_TYPE_SIZE(glob_t);
145CHECK_SIZE_AND_OFFSET(glob_t, gl_pathc);
146CHECK_SIZE_AND_OFFSET(glob_t, gl_pathv);
147CHECK_SIZE_AND_OFFSET(glob_t, gl_offs);
148CHECK_SIZE_AND_OFFSET(glob_t, gl_flags);
149CHECK_SIZE_AND_OFFSET(glob_t, gl_closedir);
150CHECK_SIZE_AND_OFFSET(glob_t, gl_readdir);
151CHECK_SIZE_AND_OFFSET(glob_t, gl_opendir);
152CHECK_SIZE_AND_OFFSET(glob_t, gl_lstat);
153CHECK_SIZE_AND_OFFSET(glob_t, gl_stat);
154
155CHECK_TYPE_SIZE(addrinfo);
156CHECK_SIZE_AND_OFFSET(addrinfo, ai_flags);
157CHECK_SIZE_AND_OFFSET(addrinfo, ai_family);
158CHECK_SIZE_AND_OFFSET(addrinfo, ai_socktype);
159CHECK_SIZE_AND_OFFSET(addrinfo, ai_protocol);
160CHECK_SIZE_AND_OFFSET(addrinfo, ai_addrlen);
161CHECK_SIZE_AND_OFFSET(addrinfo, ai_addr);
162CHECK_SIZE_AND_OFFSET(addrinfo, ai_canonname);
163CHECK_SIZE_AND_OFFSET(addrinfo, ai_next);
164
165CHECK_TYPE_SIZE(hostent);
166CHECK_SIZE_AND_OFFSET(hostent, h_name);
167CHECK_SIZE_AND_OFFSET(hostent, h_aliases);
168CHECK_SIZE_AND_OFFSET(hostent, h_addrtype);
169CHECK_SIZE_AND_OFFSET(hostent, h_length);
170CHECK_SIZE_AND_OFFSET(hostent, h_addr_list);
171
172CHECK_TYPE_SIZE(iovec);
173CHECK_SIZE_AND_OFFSET(iovec, iov_base);
174CHECK_SIZE_AND_OFFSET(iovec, iov_len);
175
176CHECK_TYPE_SIZE(msghdr);
177CHECK_SIZE_AND_OFFSET(msghdr, msg_name);
178CHECK_SIZE_AND_OFFSET(msghdr, msg_namelen);
179CHECK_SIZE_AND_OFFSET(msghdr, msg_iov);
180CHECK_SIZE_AND_OFFSET(msghdr, msg_iovlen);
181CHECK_SIZE_AND_OFFSET(msghdr, msg_control);
182CHECK_SIZE_AND_OFFSET(msghdr, msg_controllen);
183CHECK_SIZE_AND_OFFSET(msghdr, msg_flags);
184
185CHECK_TYPE_SIZE(cmsghdr);
186CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_len);
187CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_level);
188CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_type);
189
190COMPILER_CHECK(sizeof(__sanitizer_dirent) <= sizeof(dirent));
191CHECK_SIZE_AND_OFFSET(dirent, d_fileno);
192CHECK_SIZE_AND_OFFSET(dirent, d_off);
193CHECK_SIZE_AND_OFFSET(dirent, d_reclen);
194
195CHECK_TYPE_SIZE(ifconf);
196CHECK_SIZE_AND_OFFSET(ifconf, ifc_len);
197CHECK_SIZE_AND_OFFSET(ifconf, ifc_ifcu);
198
199CHECK_TYPE_SIZE(pollfd);
200CHECK_SIZE_AND_OFFSET(pollfd, fd);
201CHECK_SIZE_AND_OFFSET(pollfd, events);
202CHECK_SIZE_AND_OFFSET(pollfd, revents);
203
204CHECK_TYPE_SIZE(nfds_t);
205
206CHECK_TYPE_SIZE(sigset_t);
207
208COMPILER_CHECK(sizeof(__sanitizer_sigaction) == sizeof(struct sigaction));
209// Can't write checks for sa_handler and sa_sigaction due to them being
210// preprocessor macros.
211CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_mask);
212
213CHECK_TYPE_SIZE(tm);
214CHECK_SIZE_AND_OFFSET(tm, tm_sec);
215CHECK_SIZE_AND_OFFSET(tm, tm_min);
216CHECK_SIZE_AND_OFFSET(tm, tm_hour);
217CHECK_SIZE_AND_OFFSET(tm, tm_mday);
218CHECK_SIZE_AND_OFFSET(tm, tm_mon);
219CHECK_SIZE_AND_OFFSET(tm, tm_year);
220CHECK_SIZE_AND_OFFSET(tm, tm_wday);
221CHECK_SIZE_AND_OFFSET(tm, tm_yday);
222CHECK_SIZE_AND_OFFSET(tm, tm_isdst);
223CHECK_SIZE_AND_OFFSET(tm, tm_gmtoff);
224CHECK_SIZE_AND_OFFSET(tm, tm_zone);
225
226CHECK_TYPE_SIZE(ipc_perm);
227CHECK_SIZE_AND_OFFSET(ipc_perm, cuid);
228CHECK_SIZE_AND_OFFSET(ipc_perm, cgid);
229CHECK_SIZE_AND_OFFSET(ipc_perm, uid);
230CHECK_SIZE_AND_OFFSET(ipc_perm, gid);
231CHECK_SIZE_AND_OFFSET(ipc_perm, mode);
232CHECK_SIZE_AND_OFFSET(ipc_perm, seq);
233CHECK_SIZE_AND_OFFSET(ipc_perm, key);
234
235CHECK_TYPE_SIZE(shmid_ds);
236CHECK_SIZE_AND_OFFSET(shmid_ds, shm_perm);
237CHECK_SIZE_AND_OFFSET(shmid_ds, shm_segsz);
238CHECK_SIZE_AND_OFFSET(shmid_ds, shm_atime);
239CHECK_SIZE_AND_OFFSET(shmid_ds, __shm_atimensec);
240CHECK_SIZE_AND_OFFSET(shmid_ds, shm_dtime);
241CHECK_SIZE_AND_OFFSET(shmid_ds, __shm_dtimensec);
242CHECK_SIZE_AND_OFFSET(shmid_ds, shm_ctime);
243CHECK_SIZE_AND_OFFSET(shmid_ds, __shm_ctimensec);
244CHECK_SIZE_AND_OFFSET(shmid_ds, shm_cpid);
245CHECK_SIZE_AND_OFFSET(shmid_ds, shm_lpid);
246CHECK_SIZE_AND_OFFSET(shmid_ds, shm_nattch);
247
248CHECK_TYPE_SIZE(clock_t);
249
250CHECK_TYPE_SIZE(ifaddrs);
251CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_next);
252CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_name);
253CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_addr);
254CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_netmask);
255// Compare against the union, because we can't reach into the union in a
256// compliant way.
257#ifdef ifa_dstaddr
258#undef ifa_dstaddr
259#endif
260CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_dstaddr);
261CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_data);
262
263CHECK_TYPE_SIZE(passwd);
264CHECK_SIZE_AND_OFFSET(passwd, pw_name);
265CHECK_SIZE_AND_OFFSET(passwd, pw_passwd);
266CHECK_SIZE_AND_OFFSET(passwd, pw_uid);
267CHECK_SIZE_AND_OFFSET(passwd, pw_gid);
268CHECK_SIZE_AND_OFFSET(passwd, pw_dir);
269CHECK_SIZE_AND_OFFSET(passwd, pw_shell);
270
271CHECK_SIZE_AND_OFFSET(passwd, pw_gecos);
272
273CHECK_TYPE_SIZE(group);
274CHECK_SIZE_AND_OFFSET(group, gr_name);
275CHECK_SIZE_AND_OFFSET(group, gr_passwd);
276CHECK_SIZE_AND_OFFSET(group, gr_gid);
277CHECK_SIZE_AND_OFFSET(group, gr_mem);
278
279#endif // SANITIZER_OPENBSD
lib/tsan/sanitizer_common/sanitizer_platform_limits_openbsd.h created+382
...@@ -0,0 +1,382 @@
1//===-- sanitizer_platform_limits_openbsd.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// Sizes and layouts of platform-specific OpenBSD data structures.
12//===----------------------------------------------------------------------===//
13
14#ifndef SANITIZER_PLATFORM_LIMITS_OPENBSD_H
15#define SANITIZER_PLATFORM_LIMITS_OPENBSD_H
16
17#if SANITIZER_OPENBSD
18
19#include "sanitizer_internal_defs.h"
20#include "sanitizer_platform.h"
21
22#define _GET_LINK_MAP_BY_DLOPEN_HANDLE(handle, shift) \
23 ((link_map *)((handle) == nullptr ? nullptr : ((char *)(handle) + (shift))))
24
25#if defined(__x86_64__)
26#define GET_LINK_MAP_BY_DLOPEN_HANDLE(handle) \
27 _GET_LINK_MAP_BY_DLOPEN_HANDLE(handle, 312)
28#elif defined(__i386__)
29#define GET_LINK_MAP_BY_DLOPEN_HANDLE(handle) \
30 _GET_LINK_MAP_BY_DLOPEN_HANDLE(handle, 164)
31#endif
32
33#define RLIMIT_AS RLIMIT_DATA
34
35namespace __sanitizer {
36extern unsigned struct_utsname_sz;
37extern unsigned struct_stat_sz;
38extern unsigned struct_rusage_sz;
39extern unsigned siginfo_t_sz;
40extern unsigned struct_itimerval_sz;
41extern unsigned pthread_t_sz;
42extern unsigned pthread_mutex_t_sz;
43extern unsigned pthread_cond_t_sz;
44extern unsigned pid_t_sz;
45extern unsigned timeval_sz;
46extern unsigned uid_t_sz;
47extern unsigned gid_t_sz;
48extern unsigned mbstate_t_sz;
49extern unsigned struct_timezone_sz;
50extern unsigned struct_tms_sz;
51extern unsigned struct_itimerspec_sz;
52extern unsigned struct_sigevent_sz;
53extern unsigned struct_stack_t_sz;
54extern unsigned struct_statfs_sz;
55extern unsigned struct_sockaddr_sz;
56
57extern unsigned struct_rlimit_sz;
58extern unsigned struct_utimbuf_sz;
59extern unsigned struct_timespec_sz;
60
61struct __sanitizer_iocb {
62 u64 aio_offset;
63 uptr aio_buf;
64 long aio_nbytes;
65 u32 aio_fildes;
66 u32 aio_lio_opcode;
67 long aio_reqprio;
68#if SANITIZER_WORDSIZE == 64
69 u8 aio_sigevent[32];
70#else
71 u8 aio_sigevent[20];
72#endif
73 u32 _state;
74 u32 _errno;
75 long _retval;
76};
77
78struct __sanitizer___sysctl_args {
79 int *name;
80 int nlen;
81 void *oldval;
82 uptr *oldlenp;
83 void *newval;
84 uptr newlen;
85};
86
87struct __sanitizer_sem_t {
88 uptr data[5];
89};
90
91struct __sanitizer_ipc_perm {
92 u32 cuid;
93 u32 cgid;
94 u32 uid;
95 u32 gid;
96 u32 mode;
97 unsigned short seq;
98 long key;
99};
100
101struct __sanitizer_shmid_ds {
102 __sanitizer_ipc_perm shm_perm;
103 int shm_segsz;
104 u32 shm_lpid;
105 u32 shm_cpid;
106 short shm_nattch;
107 u64 shm_atime;
108 long __shm_atimensec;
109 u64 shm_dtime;
110 long __shm_dtimensec;
111 u64 shm_ctime;
112 long __shm_ctimensec;
113 void *_shm_internal;
114};
115
116extern unsigned struct_msqid_ds_sz;
117extern unsigned struct_mq_attr_sz;
118extern unsigned struct_timex_sz;
119extern unsigned struct_statvfs_sz;
120
121struct __sanitizer_iovec {
122 void *iov_base;
123 uptr iov_len;
124};
125
126struct __sanitizer_ifaddrs {
127 struct __sanitizer_ifaddrs *ifa_next;
128 char *ifa_name;
129 unsigned int ifa_flags;
130 struct __sanitizer_sockaddr *ifa_addr; // (struct sockaddr *)
131 struct __sanitizer_sockaddr *ifa_netmask; // (struct sockaddr *)
132 struct __sanitizer_sockaddr *ifa_dstaddr; // (struct sockaddr *)
133 void *ifa_data;
134};
135
136typedef unsigned __sanitizer_pthread_key_t;
137
138typedef long long __sanitizer_time_t;
139typedef int __sanitizer_suseconds_t;
140
141struct __sanitizer_timeval {
142 __sanitizer_time_t tv_sec;
143 __sanitizer_suseconds_t tv_usec;
144};
145
146struct __sanitizer_itimerval {
147 struct __sanitizer_timeval it_interval;
148 struct __sanitizer_timeval it_value;
149};
150
151struct __sanitizer_passwd {
152 char *pw_name;
153 char *pw_passwd;
154 int pw_uid;
155 int pw_gid;
156 __sanitizer_time_t pw_change;
157 char *pw_class;
158 char *pw_gecos;
159 char *pw_dir;
160 char *pw_shell;
161 __sanitizer_time_t pw_expire;
162};
163
164struct __sanitizer_group {
165 char *gr_name;
166 char *gr_passwd;
167 int gr_gid;
168 char **gr_mem;
169};
170
171struct __sanitizer_ether_addr {
172 u8 octet[6];
173};
174
175struct __sanitizer_tm {
176 int tm_sec;
177 int tm_min;
178 int tm_hour;
179 int tm_mday;
180 int tm_mon;
181 int tm_year;
182 int tm_wday;
183 int tm_yday;
184 int tm_isdst;
185 long int tm_gmtoff;
186 const char *tm_zone;
187};
188
189struct __sanitizer_msghdr {
190 void *msg_name;
191 unsigned msg_namelen;
192 struct __sanitizer_iovec *msg_iov;
193 unsigned msg_iovlen;
194 void *msg_control;
195 unsigned msg_controllen;
196 int msg_flags;
197};
198struct __sanitizer_cmsghdr {
199 unsigned cmsg_len;
200 int cmsg_level;
201 int cmsg_type;
202};
203
204struct __sanitizer_dirent {
205 u64 d_fileno;
206 u64 d_off;
207 u16 d_reclen;
208};
209
210typedef u64 __sanitizer_clock_t;
211typedef u32 __sanitizer_clockid_t;
212
213typedef u32 __sanitizer___kernel_uid_t;
214typedef u32 __sanitizer___kernel_gid_t;
215typedef u64 __sanitizer___kernel_off_t;
216typedef struct {
217 u32 fds_bits[8];
218} __sanitizer___kernel_fd_set;
219
220typedef struct {
221 unsigned int pta_magic;
222 int pta_flags;
223 void *pta_private;
224} __sanitizer_pthread_attr_t;
225
226typedef unsigned int __sanitizer_sigset_t;
227
228struct __sanitizer_siginfo {
229 // The size is determined by looking at sizeof of real siginfo_t on linux.
230 u64 opaque[128 / sizeof(u64)];
231};
232
233using __sanitizer_sighandler_ptr = void (*)(int sig);
234using __sanitizer_sigactionhandler_ptr = void (*)(int sig,
235 __sanitizer_siginfo *siginfo,
236 void *uctx);
237
238struct __sanitizer_sigaction {
239 union {
240 __sanitizer_sighandler_ptr handler;
241 __sanitizer_sigactionhandler_ptr sigaction;
242 };
243 __sanitizer_sigset_t sa_mask;
244 int sa_flags;
245};
246
247typedef __sanitizer_sigset_t __sanitizer_kernel_sigset_t;
248
249struct __sanitizer_kernel_sigaction_t {
250 union {
251 void (*handler)(int signo);
252 void (*sigaction)(int signo, void *info, void *ctx);
253 };
254 unsigned long sa_flags;
255 void (*sa_restorer)(void);
256 __sanitizer_kernel_sigset_t sa_mask;
257};
258
259extern const uptr sig_ign;
260extern const uptr sig_dfl;
261extern const uptr sig_err;
262extern const uptr sa_siginfo;
263
264extern int af_inet;
265extern int af_inet6;
266uptr __sanitizer_in_addr_sz(int af);
267
268struct __sanitizer_dl_phdr_info {
269#if SANITIZER_WORDSIZE == 64
270 u64 dlpi_addr;
271#else
272 u32 dlpi_addr;
273#endif
274 const char *dlpi_name;
275 const void *dlpi_phdr;
276#if SANITIZER_WORDSIZE == 64
277 u32 dlpi_phnum;
278#else
279 u16 dlpi_phnum;
280#endif
281};
282
283extern unsigned struct_ElfW_Phdr_sz;
284
285struct __sanitizer_addrinfo {
286 int ai_flags;
287 int ai_family;
288 int ai_socktype;
289 int ai_protocol;
290 unsigned ai_addrlen;
291 struct __sanitizer_sockaddr *ai_addr;
292 char *ai_canonname;
293 struct __sanitizer_addrinfo *ai_next;
294};
295
296struct __sanitizer_hostent {
297 char *h_name;
298 char **h_aliases;
299 int h_addrtype;
300 int h_length;
301 char **h_addr_list;
302};
303
304struct __sanitizer_pollfd {
305 int fd;
306 short events;
307 short revents;
308};
309
310typedef unsigned __sanitizer_nfds_t;
311
312struct __sanitizer_glob_t {
313 int gl_pathc;
314 int gl_matchc;
315 int gl_offs;
316 int gl_flags;
317 char **gl_pathv;
318 void **gl_statv;
319 int (*gl_errfunc)(const char *, int);
320 void (*gl_closedir)(void *dirp);
321 struct dirent *(*gl_readdir)(void *dirp);
322 void *(*gl_opendir)(const char *);
323 int (*gl_lstat)(const char *, void * /* struct stat* */);
324 int (*gl_stat)(const char *, void * /* struct stat* */);
325};
326
327extern int glob_nomatch;
328extern int glob_altdirfunc;
329
330extern unsigned path_max;
331
332typedef char __sanitizer_FILE;
333#define SANITIZER_HAS_STRUCT_FILE 0
334
335extern int shmctl_ipc_stat;
336
337// This simplifies generic code
338#define struct_shminfo_sz -1
339#define struct_shm_info_sz -1
340#define shmctl_shm_stat -1
341#define shmctl_ipc_info -1
342#define shmctl_shm_info -1
343
344extern unsigned struct_utmp_sz;
345extern unsigned struct_utmpx_sz;
346
347extern int map_fixed;
348
349// ioctl arguments
350struct __sanitizer_ifconf {
351 int ifc_len;
352 union {
353 void *ifcu_req;
354 } ifc_ifcu;
355};
356
357extern const int si_SEGV_MAPERR;
358extern const int si_SEGV_ACCERR;
359} // namespace __sanitizer
360
361#define CHECK_TYPE_SIZE(TYPE) \
362 COMPILER_CHECK(sizeof(__sanitizer_##TYPE) == sizeof(TYPE))
363
364#define CHECK_SIZE_AND_OFFSET(CLASS, MEMBER) \
365 COMPILER_CHECK(sizeof(((__sanitizer_##CLASS *)NULL)->MEMBER) == \
366 sizeof(((CLASS *)NULL)->MEMBER)); \
367 COMPILER_CHECK(offsetof(__sanitizer_##CLASS, MEMBER) == \
368 offsetof(CLASS, MEMBER))
369
370// For sigaction, which is a function and struct at the same time,
371// and thus requires explicit "struct" in sizeof() expression.
372#define CHECK_STRUCT_SIZE_AND_OFFSET(CLASS, MEMBER) \
373 COMPILER_CHECK(sizeof(((struct __sanitizer_##CLASS *)NULL)->MEMBER) == \
374 sizeof(((struct CLASS *)NULL)->MEMBER)); \
375 COMPILER_CHECK(offsetof(struct __sanitizer_##CLASS, MEMBER) == \
376 offsetof(struct CLASS, MEMBER))
377
378#define SIGACTION_SYMNAME __sigaction14
379
380#endif // SANITIZER_OPENBSD
381
382#endif
lib/tsan/sanitizer_common/sanitizer_platform_limits_posix.cpp created+1275
...@@ -0,0 +1,1275 @@
1//===-- sanitizer_platform_limits_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 Sanitizer common code.
10//
11// Sizes and layouts of platform-specific POSIX data structures.
12//===----------------------------------------------------------------------===//
13
14#include "sanitizer_platform.h"
15
16#if SANITIZER_LINUX || SANITIZER_MAC
17// Tests in this file assume that off_t-dependent data structures match the
18// libc ABI. For example, struct dirent here is what readdir() function (as
19// exported from libc) returns, and not the user-facing "dirent", which
20// depends on _FILE_OFFSET_BITS setting.
21// To get this "true" dirent definition, we undefine _FILE_OFFSET_BITS below.
22#ifdef _FILE_OFFSET_BITS
23#undef _FILE_OFFSET_BITS
24#endif
25
26// Must go after undef _FILE_OFFSET_BITS.
27#include "sanitizer_glibc_version.h"
28
29#include <arpa/inet.h>
30#include <dirent.h>
31#include <grp.h>
32#include <limits.h>
33#include <net/if.h>
34#include <netdb.h>
35#include <poll.h>
36#include <pthread.h>
37#include <pwd.h>
38#include <signal.h>
39#include <stddef.h>
40#include <sys/mman.h>
41#include <sys/resource.h>
42#include <sys/socket.h>
43#include <sys/stat.h>
44#include <sys/time.h>
45#include <sys/times.h>
46#include <sys/types.h>
47#include <sys/utsname.h>
48#include <termios.h>
49#include <time.h>
50#include <wchar.h>
51#include <regex.h>
52#if !SANITIZER_MAC
53#include <utmp.h>
54#endif
55
56#if !SANITIZER_IOS
57#include <net/route.h>
58#endif
59
60#if !SANITIZER_ANDROID
61#include <fstab.h>
62#include <sys/mount.h>
63#include <sys/timeb.h>
64#include <utmpx.h>
65#endif
66
67#if SANITIZER_LINUX
68#include <malloc.h>
69#include <mntent.h>
70#include <netinet/ether.h>
71#include <sys/sysinfo.h>
72#include <sys/vt.h>
73#include <linux/cdrom.h>
74#include <linux/fd.h>
75#include <linux/fs.h>
76#include <linux/hdreg.h>
77#include <linux/input.h>
78#include <linux/ioctl.h>
79#include <linux/soundcard.h>
80#include <linux/sysctl.h>
81#include <linux/utsname.h>
82#include <linux/posix_types.h>
83#include <net/if_arp.h>
84#endif
85
86#if SANITIZER_IOS
87#undef IOC_DIRMASK
88#endif
89
90#if SANITIZER_LINUX
91# include <utime.h>
92# include <sys/ptrace.h>
93# if defined(__mips64) || defined(__aarch64__) || defined(__arm__)
94# include <asm/ptrace.h>
95# ifdef __arm__
96typedef struct user_fpregs elf_fpregset_t;
97# define ARM_VFPREGS_SIZE_ASAN (32 * 8 /*fpregs*/ + 4 /*fpscr*/)
98# if !defined(ARM_VFPREGS_SIZE)
99# define ARM_VFPREGS_SIZE ARM_VFPREGS_SIZE_ASAN
100# endif
101# endif
102# endif
103# include <semaphore.h>
104#endif
105
106#if !SANITIZER_ANDROID
107#include <ifaddrs.h>
108#include <sys/ucontext.h>
109#include <wordexp.h>
110#endif
111
112#if SANITIZER_LINUX && !SANITIZER_ANDROID
113#include <glob.h>
114#include <obstack.h>
115#include <mqueue.h>
116#include <net/if_ppp.h>
117#include <netax25/ax25.h>
118#include <netipx/ipx.h>
119#include <netrom/netrom.h>
120#if HAVE_RPC_XDR_H
121# include <rpc/xdr.h>
122#endif
123#include <scsi/scsi.h>
124#include <sys/mtio.h>
125#include <sys/kd.h>
126#include <sys/shm.h>
127#include <sys/statvfs.h>
128#include <sys/timex.h>
129#if defined(__mips64)
130# include <sys/procfs.h>
131#endif
132#include <sys/user.h>
133#include <linux/cyclades.h>
134#include <linux/if_eql.h>
135#include <linux/if_plip.h>
136#include <linux/lp.h>
137#include <linux/mroute.h>
138#include <linux/mroute6.h>
139#include <linux/scc.h>
140#include <linux/serial.h>
141#include <sys/msg.h>
142#include <sys/ipc.h>
143#include <crypt.h>
144#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
145
146#if SANITIZER_ANDROID
147#include <linux/kd.h>
148#include <linux/mtio.h>
149#include <linux/ppp_defs.h>
150#include <linux/if_ppp.h>
151#endif
152
153#if SANITIZER_LINUX
154#include <link.h>
155#include <sys/vfs.h>
156#include <sys/epoll.h>
157#include <linux/capability.h>
158#endif // SANITIZER_LINUX
159
160#if SANITIZER_MAC
161#include <net/ethernet.h>
162#include <sys/filio.h>
163#include <sys/sockio.h>
164#endif
165
166// Include these after system headers to avoid name clashes and ambiguities.
167#include "sanitizer_internal_defs.h"
168#include "sanitizer_platform_limits_posix.h"
169
170namespace __sanitizer {
171 unsigned struct_utsname_sz = sizeof(struct utsname);
172 unsigned struct_stat_sz = sizeof(struct stat);
173#if !SANITIZER_IOS && !(SANITIZER_MAC && TARGET_CPU_ARM64)
174 unsigned struct_stat64_sz = sizeof(struct stat64);
175#endif // !SANITIZER_IOS && !(SANITIZER_MAC && TARGET_CPU_ARM64)
176 unsigned struct_rusage_sz = sizeof(struct rusage);
177 unsigned struct_tm_sz = sizeof(struct tm);
178 unsigned struct_passwd_sz = sizeof(struct passwd);
179 unsigned struct_group_sz = sizeof(struct group);
180 unsigned siginfo_t_sz = sizeof(siginfo_t);
181 unsigned struct_sigaction_sz = sizeof(struct sigaction);
182 unsigned struct_stack_t_sz = sizeof(stack_t);
183 unsigned struct_itimerval_sz = sizeof(struct itimerval);
184 unsigned pthread_t_sz = sizeof(pthread_t);
185 unsigned pthread_mutex_t_sz = sizeof(pthread_mutex_t);
186 unsigned pthread_cond_t_sz = sizeof(pthread_cond_t);
187 unsigned pid_t_sz = sizeof(pid_t);
188 unsigned timeval_sz = sizeof(timeval);
189 unsigned uid_t_sz = sizeof(uid_t);
190 unsigned gid_t_sz = sizeof(gid_t);
191 unsigned mbstate_t_sz = sizeof(mbstate_t);
192 unsigned sigset_t_sz = sizeof(sigset_t);
193 unsigned struct_timezone_sz = sizeof(struct timezone);
194 unsigned struct_tms_sz = sizeof(struct tms);
195 unsigned struct_sigevent_sz = sizeof(struct sigevent);
196 unsigned struct_sched_param_sz = sizeof(struct sched_param);
197 unsigned struct_regex_sz = sizeof(regex_t);
198 unsigned struct_regmatch_sz = sizeof(regmatch_t);
199
200#if (SANITIZER_MAC && !TARGET_CPU_ARM64) && !SANITIZER_IOS
201 unsigned struct_statfs64_sz = sizeof(struct statfs64);
202#endif // (SANITIZER_MAC && !TARGET_CPU_ARM64) && !SANITIZER_IOS
203
204#if !SANITIZER_ANDROID
205 unsigned struct_fstab_sz = sizeof(struct fstab);
206 unsigned struct_statfs_sz = sizeof(struct statfs);
207 unsigned struct_sockaddr_sz = sizeof(struct sockaddr);
208 unsigned ucontext_t_sz = sizeof(ucontext_t);
209#endif // !SANITIZER_ANDROID
210
211#if SANITIZER_LINUX
212 unsigned struct_epoll_event_sz = sizeof(struct epoll_event);
213 unsigned struct_sysinfo_sz = sizeof(struct sysinfo);
214 unsigned __user_cap_header_struct_sz =
215 sizeof(struct __user_cap_header_struct);
216 unsigned __user_cap_data_struct_sz = sizeof(struct __user_cap_data_struct);
217 unsigned struct_new_utsname_sz = sizeof(struct new_utsname);
218 unsigned struct_old_utsname_sz = sizeof(struct old_utsname);
219 unsigned struct_oldold_utsname_sz = sizeof(struct oldold_utsname);
220#endif // SANITIZER_LINUX
221
222#if SANITIZER_LINUX
223 unsigned struct_rlimit_sz = sizeof(struct rlimit);
224 unsigned struct_timespec_sz = sizeof(struct timespec);
225 unsigned struct_utimbuf_sz = sizeof(struct utimbuf);
226 unsigned struct_itimerspec_sz = sizeof(struct itimerspec);
227#endif // SANITIZER_LINUX
228
229#if SANITIZER_LINUX && !SANITIZER_ANDROID
230 // Use pre-computed size of struct ustat to avoid <sys/ustat.h> which
231 // has been removed from glibc 2.28.
232#if defined(__aarch64__) || defined(__s390x__) || defined (__mips64) \
233 || defined(__powerpc64__) || defined(__arch64__) || defined(__sparcv9) \
234 || defined(__x86_64__) || (defined(__riscv) && __riscv_xlen == 64)
235#define SIZEOF_STRUCT_USTAT 32
236#elif defined(__arm__) || defined(__i386__) || defined(__mips__) \
237 || defined(__powerpc__) || defined(__s390__) || defined(__sparc__)
238#define SIZEOF_STRUCT_USTAT 20
239#else
240#error Unknown size of struct ustat
241#endif
242 unsigned struct_ustat_sz = SIZEOF_STRUCT_USTAT;
243 unsigned struct_rlimit64_sz = sizeof(struct rlimit64);
244 unsigned struct_statvfs64_sz = sizeof(struct statvfs64);
245 unsigned struct_crypt_data_sz = sizeof(struct crypt_data);
246#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
247
248#if SANITIZER_LINUX && !SANITIZER_ANDROID
249 unsigned struct_timex_sz = sizeof(struct timex);
250 unsigned struct_msqid_ds_sz = sizeof(struct msqid_ds);
251 unsigned struct_mq_attr_sz = sizeof(struct mq_attr);
252 unsigned struct_statvfs_sz = sizeof(struct statvfs);
253#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
254
255 const uptr sig_ign = (uptr)SIG_IGN;
256 const uptr sig_dfl = (uptr)SIG_DFL;
257 const uptr sig_err = (uptr)SIG_ERR;
258 const uptr sa_siginfo = (uptr)SA_SIGINFO;
259
260#if SANITIZER_LINUX
261 int e_tabsz = (int)E_TABSZ;
262#endif
263
264
265#if SANITIZER_LINUX && !SANITIZER_ANDROID
266 unsigned struct_shminfo_sz = sizeof(struct shminfo);
267 unsigned struct_shm_info_sz = sizeof(struct shm_info);
268 int shmctl_ipc_stat = (int)IPC_STAT;
269 int shmctl_ipc_info = (int)IPC_INFO;
270 int shmctl_shm_info = (int)SHM_INFO;
271 int shmctl_shm_stat = (int)SHM_STAT;
272#endif
273
274#if !SANITIZER_MAC && !SANITIZER_FREEBSD
275 unsigned struct_utmp_sz = sizeof(struct utmp);
276#endif
277#if !SANITIZER_ANDROID
278 unsigned struct_utmpx_sz = sizeof(struct utmpx);
279#endif
280
281 int map_fixed = MAP_FIXED;
282
283 int af_inet = (int)AF_INET;
284 int af_inet6 = (int)AF_INET6;
285
286 uptr __sanitizer_in_addr_sz(int af) {
287 if (af == AF_INET)
288 return sizeof(struct in_addr);
289 else if (af == AF_INET6)
290 return sizeof(struct in6_addr);
291 else
292 return 0;
293 }
294
295#if SANITIZER_LINUX
296unsigned struct_ElfW_Phdr_sz = sizeof(ElfW(Phdr));
297#elif SANITIZER_FREEBSD
298unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
299#endif
300
301#if SANITIZER_LINUX && !SANITIZER_ANDROID
302 int glob_nomatch = GLOB_NOMATCH;
303 int glob_altdirfunc = GLOB_ALTDIRFUNC;
304#endif
305
306#if SANITIZER_LINUX && !SANITIZER_ANDROID && \
307 (defined(__i386) || defined(__x86_64) || defined(__mips64) || \
308 defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \
309 defined(__s390__))
310#if defined(__mips64) || defined(__powerpc64__) || defined(__arm__)
311 unsigned struct_user_regs_struct_sz = sizeof(struct pt_regs);
312 unsigned struct_user_fpregs_struct_sz = sizeof(elf_fpregset_t);
313#elif defined(__aarch64__)
314 unsigned struct_user_regs_struct_sz = sizeof(struct user_pt_regs);
315 unsigned struct_user_fpregs_struct_sz = sizeof(struct user_fpsimd_state);
316#elif defined(__s390__)
317 unsigned struct_user_regs_struct_sz = sizeof(struct _user_regs_struct);
318 unsigned struct_user_fpregs_struct_sz = sizeof(struct _user_fpregs_struct);
319#else
320 unsigned struct_user_regs_struct_sz = sizeof(struct user_regs_struct);
321 unsigned struct_user_fpregs_struct_sz = sizeof(struct user_fpregs_struct);
322#endif // __mips64 || __powerpc64__ || __aarch64__
323#if defined(__x86_64) || defined(__mips64) || defined(__powerpc64__) || \
324 defined(__aarch64__) || defined(__arm__) || defined(__s390__)
325 unsigned struct_user_fpxregs_struct_sz = 0;
326#else
327 unsigned struct_user_fpxregs_struct_sz = sizeof(struct user_fpxregs_struct);
328#endif // __x86_64 || __mips64 || __powerpc64__ || __aarch64__ || __arm__
329// || __s390__
330#ifdef __arm__
331 unsigned struct_user_vfpregs_struct_sz = ARM_VFPREGS_SIZE;
332#else
333 unsigned struct_user_vfpregs_struct_sz = 0;
334#endif
335
336 int ptrace_peektext = PTRACE_PEEKTEXT;
337 int ptrace_peekdata = PTRACE_PEEKDATA;
338 int ptrace_peekuser = PTRACE_PEEKUSER;
339#if (defined(PTRACE_GETREGS) && defined(PTRACE_SETREGS)) || \
340 (defined(PT_GETREGS) && defined(PT_SETREGS))
341 int ptrace_getregs = PTRACE_GETREGS;
342 int ptrace_setregs = PTRACE_SETREGS;
343#else
344 int ptrace_getregs = -1;
345 int ptrace_setregs = -1;
346#endif
347#if (defined(PTRACE_GETFPREGS) && defined(PTRACE_SETFPREGS)) || \
348 (defined(PT_GETFPREGS) && defined(PT_SETFPREGS))
349 int ptrace_getfpregs = PTRACE_GETFPREGS;
350 int ptrace_setfpregs = PTRACE_SETFPREGS;
351#else
352 int ptrace_getfpregs = -1;
353 int ptrace_setfpregs = -1;
354#endif
355#if (defined(PTRACE_GETFPXREGS) && defined(PTRACE_SETFPXREGS)) || \
356 (defined(PT_GETFPXREGS) && defined(PT_SETFPXREGS))
357 int ptrace_getfpxregs = PTRACE_GETFPXREGS;
358 int ptrace_setfpxregs = PTRACE_SETFPXREGS;
359#else
360 int ptrace_getfpxregs = -1;
361 int ptrace_setfpxregs = -1;
362#endif // PTRACE_GETFPXREGS/PTRACE_SETFPXREGS
363#if defined(PTRACE_GETVFPREGS) && defined(PTRACE_SETVFPREGS)
364 int ptrace_getvfpregs = PTRACE_GETVFPREGS;
365 int ptrace_setvfpregs = PTRACE_SETVFPREGS;
366#else
367 int ptrace_getvfpregs = -1;
368 int ptrace_setvfpregs = -1;
369#endif
370 int ptrace_geteventmsg = PTRACE_GETEVENTMSG;
371#if (defined(PTRACE_GETSIGINFO) && defined(PTRACE_SETSIGINFO)) || \
372 (defined(PT_GETSIGINFO) && defined(PT_SETSIGINFO))
373 int ptrace_getsiginfo = PTRACE_GETSIGINFO;
374 int ptrace_setsiginfo = PTRACE_SETSIGINFO;
375#else
376 int ptrace_getsiginfo = -1;
377 int ptrace_setsiginfo = -1;
378#endif // PTRACE_GETSIGINFO/PTRACE_SETSIGINFO
379#if defined(PTRACE_GETREGSET) && defined(PTRACE_SETREGSET)
380 int ptrace_getregset = PTRACE_GETREGSET;
381 int ptrace_setregset = PTRACE_SETREGSET;
382#else
383 int ptrace_getregset = -1;
384 int ptrace_setregset = -1;
385#endif // PTRACE_GETREGSET/PTRACE_SETREGSET
386#endif
387
388 unsigned path_max = PATH_MAX;
389
390 // ioctl arguments
391 unsigned struct_ifreq_sz = sizeof(struct ifreq);
392 unsigned struct_termios_sz = sizeof(struct termios);
393 unsigned struct_winsize_sz = sizeof(struct winsize);
394
395#if SANITIZER_LINUX
396 unsigned struct_arpreq_sz = sizeof(struct arpreq);
397 unsigned struct_cdrom_msf_sz = sizeof(struct cdrom_msf);
398 unsigned struct_cdrom_multisession_sz = sizeof(struct cdrom_multisession);
399 unsigned struct_cdrom_read_audio_sz = sizeof(struct cdrom_read_audio);
400 unsigned struct_cdrom_subchnl_sz = sizeof(struct cdrom_subchnl);
401 unsigned struct_cdrom_ti_sz = sizeof(struct cdrom_ti);
402 unsigned struct_cdrom_tocentry_sz = sizeof(struct cdrom_tocentry);
403 unsigned struct_cdrom_tochdr_sz = sizeof(struct cdrom_tochdr);
404 unsigned struct_cdrom_volctrl_sz = sizeof(struct cdrom_volctrl);
405 unsigned struct_ff_effect_sz = sizeof(struct ff_effect);
406 unsigned struct_floppy_drive_params_sz = sizeof(struct floppy_drive_params);
407 unsigned struct_floppy_drive_struct_sz = sizeof(struct floppy_drive_struct);
408 unsigned struct_floppy_fdc_state_sz = sizeof(struct floppy_fdc_state);
409 unsigned struct_floppy_max_errors_sz = sizeof(struct floppy_max_errors);
410 unsigned struct_floppy_raw_cmd_sz = sizeof(struct floppy_raw_cmd);
411 unsigned struct_floppy_struct_sz = sizeof(struct floppy_struct);
412 unsigned struct_floppy_write_errors_sz = sizeof(struct floppy_write_errors);
413 unsigned struct_format_descr_sz = sizeof(struct format_descr);
414 unsigned struct_hd_driveid_sz = sizeof(struct hd_driveid);
415 unsigned struct_hd_geometry_sz = sizeof(struct hd_geometry);
416 unsigned struct_input_absinfo_sz = sizeof(struct input_absinfo);
417 unsigned struct_input_id_sz = sizeof(struct input_id);
418 unsigned struct_mtpos_sz = sizeof(struct mtpos);
419 unsigned struct_rtentry_sz = sizeof(struct rtentry);
420 unsigned struct_termio_sz = sizeof(struct termio);
421 unsigned struct_vt_consize_sz = sizeof(struct vt_consize);
422 unsigned struct_vt_sizes_sz = sizeof(struct vt_sizes);
423 unsigned struct_vt_stat_sz = sizeof(struct vt_stat);
424#endif // SANITIZER_LINUX
425
426#if SANITIZER_LINUX
427#if SOUND_VERSION >= 0x040000
428 unsigned struct_copr_buffer_sz = 0;
429 unsigned struct_copr_debug_buf_sz = 0;
430 unsigned struct_copr_msg_sz = 0;
431#else
432 unsigned struct_copr_buffer_sz = sizeof(struct copr_buffer);
433 unsigned struct_copr_debug_buf_sz = sizeof(struct copr_debug_buf);
434 unsigned struct_copr_msg_sz = sizeof(struct copr_msg);
435#endif
436 unsigned struct_midi_info_sz = sizeof(struct midi_info);
437 unsigned struct_mtget_sz = sizeof(struct mtget);
438 unsigned struct_mtop_sz = sizeof(struct mtop);
439 unsigned struct_sbi_instrument_sz = sizeof(struct sbi_instrument);
440 unsigned struct_seq_event_rec_sz = sizeof(struct seq_event_rec);
441 unsigned struct_synth_info_sz = sizeof(struct synth_info);
442 unsigned struct_vt_mode_sz = sizeof(struct vt_mode);
443#endif // SANITIZER_LINUX
444
445#if SANITIZER_LINUX && !SANITIZER_ANDROID
446 unsigned struct_ax25_parms_struct_sz = sizeof(struct ax25_parms_struct);
447 unsigned struct_cyclades_monitor_sz = sizeof(struct cyclades_monitor);
448#if EV_VERSION > (0x010000)
449 unsigned struct_input_keymap_entry_sz = sizeof(struct input_keymap_entry);
450#else
451 unsigned struct_input_keymap_entry_sz = 0;
452#endif
453 unsigned struct_ipx_config_data_sz = sizeof(struct ipx_config_data);
454 unsigned struct_kbdiacrs_sz = sizeof(struct kbdiacrs);
455 unsigned struct_kbentry_sz = sizeof(struct kbentry);
456 unsigned struct_kbkeycode_sz = sizeof(struct kbkeycode);
457 unsigned struct_kbsentry_sz = sizeof(struct kbsentry);
458 unsigned struct_mtconfiginfo_sz = sizeof(struct mtconfiginfo);
459 unsigned struct_nr_parms_struct_sz = sizeof(struct nr_parms_struct);
460 unsigned struct_scc_modem_sz = sizeof(struct scc_modem);
461 unsigned struct_scc_stat_sz = sizeof(struct scc_stat);
462 unsigned struct_serial_multiport_struct_sz
463 = sizeof(struct serial_multiport_struct);
464 unsigned struct_serial_struct_sz = sizeof(struct serial_struct);
465 unsigned struct_sockaddr_ax25_sz = sizeof(struct sockaddr_ax25);
466 unsigned struct_unimapdesc_sz = sizeof(struct unimapdesc);
467 unsigned struct_unimapinit_sz = sizeof(struct unimapinit);
468#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
469
470#if SANITIZER_LINUX && !SANITIZER_ANDROID
471 unsigned struct_audio_buf_info_sz = sizeof(struct audio_buf_info);
472 unsigned struct_ppp_stats_sz = sizeof(struct ppp_stats);
473#endif // (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID
474
475#if !SANITIZER_ANDROID && !SANITIZER_MAC
476 unsigned struct_sioc_sg_req_sz = sizeof(struct sioc_sg_req);
477 unsigned struct_sioc_vif_req_sz = sizeof(struct sioc_vif_req);
478#endif
479
480 const unsigned long __sanitizer_bufsiz = BUFSIZ;
481
482 const unsigned IOCTL_NOT_PRESENT = 0;
483
484 unsigned IOCTL_FIOASYNC = FIOASYNC;
485 unsigned IOCTL_FIOCLEX = FIOCLEX;
486 unsigned IOCTL_FIOGETOWN = FIOGETOWN;
487 unsigned IOCTL_FIONBIO = FIONBIO;
488 unsigned IOCTL_FIONCLEX = FIONCLEX;
489 unsigned IOCTL_FIOSETOWN = FIOSETOWN;
490 unsigned IOCTL_SIOCADDMULTI = SIOCADDMULTI;
491 unsigned IOCTL_SIOCATMARK = SIOCATMARK;
492 unsigned IOCTL_SIOCDELMULTI = SIOCDELMULTI;
493 unsigned IOCTL_SIOCGIFADDR = SIOCGIFADDR;
494 unsigned IOCTL_SIOCGIFBRDADDR = SIOCGIFBRDADDR;
495 unsigned IOCTL_SIOCGIFCONF = SIOCGIFCONF;
496 unsigned IOCTL_SIOCGIFDSTADDR = SIOCGIFDSTADDR;
497 unsigned IOCTL_SIOCGIFFLAGS = SIOCGIFFLAGS;
498 unsigned IOCTL_SIOCGIFMETRIC = SIOCGIFMETRIC;
499 unsigned IOCTL_SIOCGIFMTU = SIOCGIFMTU;
500 unsigned IOCTL_SIOCGIFNETMASK = SIOCGIFNETMASK;
501 unsigned IOCTL_SIOCGPGRP = SIOCGPGRP;
502 unsigned IOCTL_SIOCSIFADDR = SIOCSIFADDR;
503 unsigned IOCTL_SIOCSIFBRDADDR = SIOCSIFBRDADDR;
504 unsigned IOCTL_SIOCSIFDSTADDR = SIOCSIFDSTADDR;
505 unsigned IOCTL_SIOCSIFFLAGS = SIOCSIFFLAGS;
506 unsigned IOCTL_SIOCSIFMETRIC = SIOCSIFMETRIC;
507 unsigned IOCTL_SIOCSIFMTU = SIOCSIFMTU;
508 unsigned IOCTL_SIOCSIFNETMASK = SIOCSIFNETMASK;
509 unsigned IOCTL_SIOCSPGRP = SIOCSPGRP;
510 unsigned IOCTL_TIOCCONS = TIOCCONS;
511 unsigned IOCTL_TIOCEXCL = TIOCEXCL;
512 unsigned IOCTL_TIOCGETD = TIOCGETD;
513 unsigned IOCTL_TIOCGPGRP = TIOCGPGRP;
514 unsigned IOCTL_TIOCGWINSZ = TIOCGWINSZ;
515 unsigned IOCTL_TIOCMBIC = TIOCMBIC;
516 unsigned IOCTL_TIOCMBIS = TIOCMBIS;
517 unsigned IOCTL_TIOCMGET = TIOCMGET;
518 unsigned IOCTL_TIOCMSET = TIOCMSET;
519 unsigned IOCTL_TIOCNOTTY = TIOCNOTTY;
520 unsigned IOCTL_TIOCNXCL = TIOCNXCL;
521 unsigned IOCTL_TIOCOUTQ = TIOCOUTQ;
522 unsigned IOCTL_TIOCPKT = TIOCPKT;
523 unsigned IOCTL_TIOCSCTTY = TIOCSCTTY;
524 unsigned IOCTL_TIOCSETD = TIOCSETD;
525 unsigned IOCTL_TIOCSPGRP = TIOCSPGRP;
526 unsigned IOCTL_TIOCSTI = TIOCSTI;
527 unsigned IOCTL_TIOCSWINSZ = TIOCSWINSZ;
528#if SANITIZER_LINUX && !SANITIZER_ANDROID
529 unsigned IOCTL_SIOCGETSGCNT = SIOCGETSGCNT;
530 unsigned IOCTL_SIOCGETVIFCNT = SIOCGETVIFCNT;
531#endif
532
533#if SANITIZER_LINUX
534 unsigned IOCTL_EVIOCGABS = EVIOCGABS(0);
535 unsigned IOCTL_EVIOCGBIT = EVIOCGBIT(0, 0);
536 unsigned IOCTL_EVIOCGEFFECTS = EVIOCGEFFECTS;
537 unsigned IOCTL_EVIOCGID = EVIOCGID;
538 unsigned IOCTL_EVIOCGKEY = EVIOCGKEY(0);
539 unsigned IOCTL_EVIOCGKEYCODE = EVIOCGKEYCODE;
540 unsigned IOCTL_EVIOCGLED = EVIOCGLED(0);
541 unsigned IOCTL_EVIOCGNAME = EVIOCGNAME(0);
542 unsigned IOCTL_EVIOCGPHYS = EVIOCGPHYS(0);
543 unsigned IOCTL_EVIOCGRAB = EVIOCGRAB;
544 unsigned IOCTL_EVIOCGREP = EVIOCGREP;
545 unsigned IOCTL_EVIOCGSND = EVIOCGSND(0);
546 unsigned IOCTL_EVIOCGSW = EVIOCGSW(0);
547 unsigned IOCTL_EVIOCGUNIQ = EVIOCGUNIQ(0);
548 unsigned IOCTL_EVIOCGVERSION = EVIOCGVERSION;
549 unsigned IOCTL_EVIOCRMFF = EVIOCRMFF;
550 unsigned IOCTL_EVIOCSABS = EVIOCSABS(0);
551 unsigned IOCTL_EVIOCSFF = EVIOCSFF;
552 unsigned IOCTL_EVIOCSKEYCODE = EVIOCSKEYCODE;
553 unsigned IOCTL_EVIOCSREP = EVIOCSREP;
554 unsigned IOCTL_BLKFLSBUF = BLKFLSBUF;
555 unsigned IOCTL_BLKGETSIZE = BLKGETSIZE;
556 unsigned IOCTL_BLKRAGET = BLKRAGET;
557 unsigned IOCTL_BLKRASET = BLKRASET;
558 unsigned IOCTL_BLKROGET = BLKROGET;
559 unsigned IOCTL_BLKROSET = BLKROSET;
560 unsigned IOCTL_BLKRRPART = BLKRRPART;
561 unsigned IOCTL_CDROMAUDIOBUFSIZ = CDROMAUDIOBUFSIZ;
562 unsigned IOCTL_CDROMEJECT = CDROMEJECT;
563 unsigned IOCTL_CDROMEJECT_SW = CDROMEJECT_SW;
564 unsigned IOCTL_CDROMMULTISESSION = CDROMMULTISESSION;
565 unsigned IOCTL_CDROMPAUSE = CDROMPAUSE;
566 unsigned IOCTL_CDROMPLAYMSF = CDROMPLAYMSF;
567 unsigned IOCTL_CDROMPLAYTRKIND = CDROMPLAYTRKIND;
568 unsigned IOCTL_CDROMREADAUDIO = CDROMREADAUDIO;
569 unsigned IOCTL_CDROMREADCOOKED = CDROMREADCOOKED;
570 unsigned IOCTL_CDROMREADMODE1 = CDROMREADMODE1;
571 unsigned IOCTL_CDROMREADMODE2 = CDROMREADMODE2;
572 unsigned IOCTL_CDROMREADRAW = CDROMREADRAW;
573 unsigned IOCTL_CDROMREADTOCENTRY = CDROMREADTOCENTRY;
574 unsigned IOCTL_CDROMREADTOCHDR = CDROMREADTOCHDR;
575 unsigned IOCTL_CDROMRESET = CDROMRESET;
576 unsigned IOCTL_CDROMRESUME = CDROMRESUME;
577 unsigned IOCTL_CDROMSEEK = CDROMSEEK;
578 unsigned IOCTL_CDROMSTART = CDROMSTART;
579 unsigned IOCTL_CDROMSTOP = CDROMSTOP;
580 unsigned IOCTL_CDROMSUBCHNL = CDROMSUBCHNL;
581 unsigned IOCTL_CDROMVOLCTRL = CDROMVOLCTRL;
582 unsigned IOCTL_CDROMVOLREAD = CDROMVOLREAD;
583 unsigned IOCTL_CDROM_GET_UPC = CDROM_GET_UPC;
584 unsigned IOCTL_FDCLRPRM = FDCLRPRM;
585 unsigned IOCTL_FDDEFPRM = FDDEFPRM;
586 unsigned IOCTL_FDFLUSH = FDFLUSH;
587 unsigned IOCTL_FDFMTBEG = FDFMTBEG;
588 unsigned IOCTL_FDFMTEND = FDFMTEND;
589 unsigned IOCTL_FDFMTTRK = FDFMTTRK;
590 unsigned IOCTL_FDGETDRVPRM = FDGETDRVPRM;
591 unsigned IOCTL_FDGETDRVSTAT = FDGETDRVSTAT;
592 unsigned IOCTL_FDGETDRVTYP = FDGETDRVTYP;
593 unsigned IOCTL_FDGETFDCSTAT = FDGETFDCSTAT;
594 unsigned IOCTL_FDGETMAXERRS = FDGETMAXERRS;
595 unsigned IOCTL_FDGETPRM = FDGETPRM;
596 unsigned IOCTL_FDMSGOFF = FDMSGOFF;
597 unsigned IOCTL_FDMSGON = FDMSGON;
598 unsigned IOCTL_FDPOLLDRVSTAT = FDPOLLDRVSTAT;
599 unsigned IOCTL_FDRAWCMD = FDRAWCMD;
600 unsigned IOCTL_FDRESET = FDRESET;
601 unsigned IOCTL_FDSETDRVPRM = FDSETDRVPRM;
602 unsigned IOCTL_FDSETEMSGTRESH = FDSETEMSGTRESH;
603 unsigned IOCTL_FDSETMAXERRS = FDSETMAXERRS;
604 unsigned IOCTL_FDSETPRM = FDSETPRM;
605 unsigned IOCTL_FDTWADDLE = FDTWADDLE;
606 unsigned IOCTL_FDWERRORCLR = FDWERRORCLR;
607 unsigned IOCTL_FDWERRORGET = FDWERRORGET;
608 unsigned IOCTL_HDIO_DRIVE_CMD = HDIO_DRIVE_CMD;
609 unsigned IOCTL_HDIO_GETGEO = HDIO_GETGEO;
610 unsigned IOCTL_HDIO_GET_32BIT = HDIO_GET_32BIT;
611 unsigned IOCTL_HDIO_GET_DMA = HDIO_GET_DMA;
612 unsigned IOCTL_HDIO_GET_IDENTITY = HDIO_GET_IDENTITY;
613 unsigned IOCTL_HDIO_GET_KEEPSETTINGS = HDIO_GET_KEEPSETTINGS;
614 unsigned IOCTL_HDIO_GET_MULTCOUNT = HDIO_GET_MULTCOUNT;
615 unsigned IOCTL_HDIO_GET_NOWERR = HDIO_GET_NOWERR;
616 unsigned IOCTL_HDIO_GET_UNMASKINTR = HDIO_GET_UNMASKINTR;
617 unsigned IOCTL_HDIO_SET_32BIT = HDIO_SET_32BIT;
618 unsigned IOCTL_HDIO_SET_DMA = HDIO_SET_DMA;
619 unsigned IOCTL_HDIO_SET_KEEPSETTINGS = HDIO_SET_KEEPSETTINGS;
620 unsigned IOCTL_HDIO_SET_MULTCOUNT = HDIO_SET_MULTCOUNT;
621 unsigned IOCTL_HDIO_SET_NOWERR = HDIO_SET_NOWERR;
622 unsigned IOCTL_HDIO_SET_UNMASKINTR = HDIO_SET_UNMASKINTR;
623 unsigned IOCTL_MTIOCPOS = MTIOCPOS;
624 unsigned IOCTL_PPPIOCGASYNCMAP = PPPIOCGASYNCMAP;
625 unsigned IOCTL_PPPIOCGDEBUG = PPPIOCGDEBUG;
626 unsigned IOCTL_PPPIOCGFLAGS = PPPIOCGFLAGS;
627 unsigned IOCTL_PPPIOCGUNIT = PPPIOCGUNIT;
628 unsigned IOCTL_PPPIOCGXASYNCMAP = PPPIOCGXASYNCMAP;
629 unsigned IOCTL_PPPIOCSASYNCMAP = PPPIOCSASYNCMAP;
630 unsigned IOCTL_PPPIOCSDEBUG = PPPIOCSDEBUG;
631 unsigned IOCTL_PPPIOCSFLAGS = PPPIOCSFLAGS;
632 unsigned IOCTL_PPPIOCSMAXCID = PPPIOCSMAXCID;
633 unsigned IOCTL_PPPIOCSMRU = PPPIOCSMRU;
634 unsigned IOCTL_PPPIOCSXASYNCMAP = PPPIOCSXASYNCMAP;
635 unsigned IOCTL_SIOCADDRT = SIOCADDRT;
636 unsigned IOCTL_SIOCDARP = SIOCDARP;
637 unsigned IOCTL_SIOCDELRT = SIOCDELRT;
638 unsigned IOCTL_SIOCDRARP = SIOCDRARP;
639 unsigned IOCTL_SIOCGARP = SIOCGARP;
640 unsigned IOCTL_SIOCGIFENCAP = SIOCGIFENCAP;
641 unsigned IOCTL_SIOCGIFHWADDR = SIOCGIFHWADDR;
642 unsigned IOCTL_SIOCGIFMAP = SIOCGIFMAP;
643 unsigned IOCTL_SIOCGIFMEM = SIOCGIFMEM;
644 unsigned IOCTL_SIOCGIFNAME = SIOCGIFNAME;
645 unsigned IOCTL_SIOCGIFSLAVE = SIOCGIFSLAVE;
646 unsigned IOCTL_SIOCGRARP = SIOCGRARP;
647 unsigned IOCTL_SIOCGSTAMP = SIOCGSTAMP;
648 unsigned IOCTL_SIOCSARP = SIOCSARP;
649 unsigned IOCTL_SIOCSIFENCAP = SIOCSIFENCAP;
650 unsigned IOCTL_SIOCSIFHWADDR = SIOCSIFHWADDR;
651 unsigned IOCTL_SIOCSIFLINK = SIOCSIFLINK;
652 unsigned IOCTL_SIOCSIFMAP = SIOCSIFMAP;
653 unsigned IOCTL_SIOCSIFMEM = SIOCSIFMEM;
654 unsigned IOCTL_SIOCSIFSLAVE = SIOCSIFSLAVE;
655 unsigned IOCTL_SIOCSRARP = SIOCSRARP;
656# if SOUND_VERSION >= 0x040000
657 unsigned IOCTL_SNDCTL_COPR_HALT = IOCTL_NOT_PRESENT;
658 unsigned IOCTL_SNDCTL_COPR_LOAD = IOCTL_NOT_PRESENT;
659 unsigned IOCTL_SNDCTL_COPR_RCODE = IOCTL_NOT_PRESENT;
660 unsigned IOCTL_SNDCTL_COPR_RCVMSG = IOCTL_NOT_PRESENT;
661 unsigned IOCTL_SNDCTL_COPR_RDATA = IOCTL_NOT_PRESENT;
662 unsigned IOCTL_SNDCTL_COPR_RESET = IOCTL_NOT_PRESENT;
663 unsigned IOCTL_SNDCTL_COPR_RUN = IOCTL_NOT_PRESENT;
664 unsigned IOCTL_SNDCTL_COPR_SENDMSG = IOCTL_NOT_PRESENT;
665 unsigned IOCTL_SNDCTL_COPR_WCODE = IOCTL_NOT_PRESENT;
666 unsigned IOCTL_SNDCTL_COPR_WDATA = IOCTL_NOT_PRESENT;
667 unsigned IOCTL_SOUND_PCM_READ_BITS = IOCTL_NOT_PRESENT;
668 unsigned IOCTL_SOUND_PCM_READ_CHANNELS = IOCTL_NOT_PRESENT;
669 unsigned IOCTL_SOUND_PCM_READ_FILTER = IOCTL_NOT_PRESENT;
670 unsigned IOCTL_SOUND_PCM_READ_RATE = IOCTL_NOT_PRESENT;
671 unsigned IOCTL_SOUND_PCM_WRITE_CHANNELS = IOCTL_NOT_PRESENT;
672 unsigned IOCTL_SOUND_PCM_WRITE_FILTER = IOCTL_NOT_PRESENT;
673# else // SOUND_VERSION
674 unsigned IOCTL_SNDCTL_COPR_HALT = SNDCTL_COPR_HALT;
675 unsigned IOCTL_SNDCTL_COPR_LOAD = SNDCTL_COPR_LOAD;
676 unsigned IOCTL_SNDCTL_COPR_RCODE = SNDCTL_COPR_RCODE;
677 unsigned IOCTL_SNDCTL_COPR_RCVMSG = SNDCTL_COPR_RCVMSG;
678 unsigned IOCTL_SNDCTL_COPR_RDATA = SNDCTL_COPR_RDATA;
679 unsigned IOCTL_SNDCTL_COPR_RESET = SNDCTL_COPR_RESET;
680 unsigned IOCTL_SNDCTL_COPR_RUN = SNDCTL_COPR_RUN;
681 unsigned IOCTL_SNDCTL_COPR_SENDMSG = SNDCTL_COPR_SENDMSG;
682 unsigned IOCTL_SNDCTL_COPR_WCODE = SNDCTL_COPR_WCODE;
683 unsigned IOCTL_SNDCTL_COPR_WDATA = SNDCTL_COPR_WDATA;
684 unsigned IOCTL_SOUND_PCM_READ_BITS = SOUND_PCM_READ_BITS;
685 unsigned IOCTL_SOUND_PCM_READ_CHANNELS = SOUND_PCM_READ_CHANNELS;
686 unsigned IOCTL_SOUND_PCM_READ_FILTER = SOUND_PCM_READ_FILTER;
687 unsigned IOCTL_SOUND_PCM_READ_RATE = SOUND_PCM_READ_RATE;
688 unsigned IOCTL_SOUND_PCM_WRITE_CHANNELS = SOUND_PCM_WRITE_CHANNELS;
689 unsigned IOCTL_SOUND_PCM_WRITE_FILTER = SOUND_PCM_WRITE_FILTER;
690#endif // SOUND_VERSION
691 unsigned IOCTL_TCFLSH = TCFLSH;
692 unsigned IOCTL_TCGETA = TCGETA;
693 unsigned IOCTL_TCGETS = TCGETS;
694 unsigned IOCTL_TCSBRK = TCSBRK;
695 unsigned IOCTL_TCSBRKP = TCSBRKP;
696 unsigned IOCTL_TCSETA = TCSETA;
697 unsigned IOCTL_TCSETAF = TCSETAF;
698 unsigned IOCTL_TCSETAW = TCSETAW;
699 unsigned IOCTL_TCSETS = TCSETS;
700 unsigned IOCTL_TCSETSF = TCSETSF;
701 unsigned IOCTL_TCSETSW = TCSETSW;
702 unsigned IOCTL_TCXONC = TCXONC;
703 unsigned IOCTL_TIOCGLCKTRMIOS = TIOCGLCKTRMIOS;
704 unsigned IOCTL_TIOCGSOFTCAR = TIOCGSOFTCAR;
705 unsigned IOCTL_TIOCINQ = TIOCINQ;
706 unsigned IOCTL_TIOCLINUX = TIOCLINUX;
707 unsigned IOCTL_TIOCSERCONFIG = TIOCSERCONFIG;
708 unsigned IOCTL_TIOCSERGETLSR = TIOCSERGETLSR;
709 unsigned IOCTL_TIOCSERGWILD = TIOCSERGWILD;
710 unsigned IOCTL_TIOCSERSWILD = TIOCSERSWILD;
711 unsigned IOCTL_TIOCSLCKTRMIOS = TIOCSLCKTRMIOS;
712 unsigned IOCTL_TIOCSSOFTCAR = TIOCSSOFTCAR;
713 unsigned IOCTL_VT_DISALLOCATE = VT_DISALLOCATE;
714 unsigned IOCTL_VT_GETSTATE = VT_GETSTATE;
715 unsigned IOCTL_VT_RESIZE = VT_RESIZE;
716 unsigned IOCTL_VT_RESIZEX = VT_RESIZEX;
717 unsigned IOCTL_VT_SENDSIG = VT_SENDSIG;
718 unsigned IOCTL_MTIOCGET = MTIOCGET;
719 unsigned IOCTL_MTIOCTOP = MTIOCTOP;
720 unsigned IOCTL_SNDCTL_DSP_GETBLKSIZE = SNDCTL_DSP_GETBLKSIZE;
721 unsigned IOCTL_SNDCTL_DSP_GETFMTS = SNDCTL_DSP_GETFMTS;
722 unsigned IOCTL_SNDCTL_DSP_NONBLOCK = SNDCTL_DSP_NONBLOCK;
723 unsigned IOCTL_SNDCTL_DSP_POST = SNDCTL_DSP_POST;
724 unsigned IOCTL_SNDCTL_DSP_RESET = SNDCTL_DSP_RESET;
725 unsigned IOCTL_SNDCTL_DSP_SETFMT = SNDCTL_DSP_SETFMT;
726 unsigned IOCTL_SNDCTL_DSP_SETFRAGMENT = SNDCTL_DSP_SETFRAGMENT;
727 unsigned IOCTL_SNDCTL_DSP_SPEED = SNDCTL_DSP_SPEED;
728 unsigned IOCTL_SNDCTL_DSP_STEREO = SNDCTL_DSP_STEREO;
729 unsigned IOCTL_SNDCTL_DSP_SUBDIVIDE = SNDCTL_DSP_SUBDIVIDE;
730 unsigned IOCTL_SNDCTL_DSP_SYNC = SNDCTL_DSP_SYNC;
731 unsigned IOCTL_SNDCTL_FM_4OP_ENABLE = SNDCTL_FM_4OP_ENABLE;
732 unsigned IOCTL_SNDCTL_FM_LOAD_INSTR = SNDCTL_FM_LOAD_INSTR;
733 unsigned IOCTL_SNDCTL_MIDI_INFO = SNDCTL_MIDI_INFO;
734 unsigned IOCTL_SNDCTL_MIDI_PRETIME = SNDCTL_MIDI_PRETIME;
735 unsigned IOCTL_SNDCTL_SEQ_CTRLRATE = SNDCTL_SEQ_CTRLRATE;
736 unsigned IOCTL_SNDCTL_SEQ_GETINCOUNT = SNDCTL_SEQ_GETINCOUNT;
737 unsigned IOCTL_SNDCTL_SEQ_GETOUTCOUNT = SNDCTL_SEQ_GETOUTCOUNT;
738 unsigned IOCTL_SNDCTL_SEQ_NRMIDIS = SNDCTL_SEQ_NRMIDIS;
739 unsigned IOCTL_SNDCTL_SEQ_NRSYNTHS = SNDCTL_SEQ_NRSYNTHS;
740 unsigned IOCTL_SNDCTL_SEQ_OUTOFBAND = SNDCTL_SEQ_OUTOFBAND;
741 unsigned IOCTL_SNDCTL_SEQ_PANIC = SNDCTL_SEQ_PANIC;
742 unsigned IOCTL_SNDCTL_SEQ_PERCMODE = SNDCTL_SEQ_PERCMODE;
743 unsigned IOCTL_SNDCTL_SEQ_RESET = SNDCTL_SEQ_RESET;
744 unsigned IOCTL_SNDCTL_SEQ_RESETSAMPLES = SNDCTL_SEQ_RESETSAMPLES;
745 unsigned IOCTL_SNDCTL_SEQ_SYNC = SNDCTL_SEQ_SYNC;
746 unsigned IOCTL_SNDCTL_SEQ_TESTMIDI = SNDCTL_SEQ_TESTMIDI;
747 unsigned IOCTL_SNDCTL_SEQ_THRESHOLD = SNDCTL_SEQ_THRESHOLD;
748 unsigned IOCTL_SNDCTL_SYNTH_INFO = SNDCTL_SYNTH_INFO;
749 unsigned IOCTL_SNDCTL_SYNTH_MEMAVL = SNDCTL_SYNTH_MEMAVL;
750 unsigned IOCTL_SNDCTL_TMR_CONTINUE = SNDCTL_TMR_CONTINUE;
751 unsigned IOCTL_SNDCTL_TMR_METRONOME = SNDCTL_TMR_METRONOME;
752 unsigned IOCTL_SNDCTL_TMR_SELECT = SNDCTL_TMR_SELECT;
753 unsigned IOCTL_SNDCTL_TMR_SOURCE = SNDCTL_TMR_SOURCE;
754 unsigned IOCTL_SNDCTL_TMR_START = SNDCTL_TMR_START;
755 unsigned IOCTL_SNDCTL_TMR_STOP = SNDCTL_TMR_STOP;
756 unsigned IOCTL_SNDCTL_TMR_TEMPO = SNDCTL_TMR_TEMPO;
757 unsigned IOCTL_SNDCTL_TMR_TIMEBASE = SNDCTL_TMR_TIMEBASE;
758 unsigned IOCTL_SOUND_MIXER_READ_ALTPCM = SOUND_MIXER_READ_ALTPCM;
759 unsigned IOCTL_SOUND_MIXER_READ_BASS = SOUND_MIXER_READ_BASS;
760 unsigned IOCTL_SOUND_MIXER_READ_CAPS = SOUND_MIXER_READ_CAPS;
761 unsigned IOCTL_SOUND_MIXER_READ_CD = SOUND_MIXER_READ_CD;
762 unsigned IOCTL_SOUND_MIXER_READ_DEVMASK = SOUND_MIXER_READ_DEVMASK;
763 unsigned IOCTL_SOUND_MIXER_READ_ENHANCE = SOUND_MIXER_READ_ENHANCE;
764 unsigned IOCTL_SOUND_MIXER_READ_IGAIN = SOUND_MIXER_READ_IGAIN;
765 unsigned IOCTL_SOUND_MIXER_READ_IMIX = SOUND_MIXER_READ_IMIX;
766 unsigned IOCTL_SOUND_MIXER_READ_LINE = SOUND_MIXER_READ_LINE;
767 unsigned IOCTL_SOUND_MIXER_READ_LINE1 = SOUND_MIXER_READ_LINE1;
768 unsigned IOCTL_SOUND_MIXER_READ_LINE2 = SOUND_MIXER_READ_LINE2;
769 unsigned IOCTL_SOUND_MIXER_READ_LINE3 = SOUND_MIXER_READ_LINE3;
770 unsigned IOCTL_SOUND_MIXER_READ_LOUD = SOUND_MIXER_READ_LOUD;
771 unsigned IOCTL_SOUND_MIXER_READ_MIC = SOUND_MIXER_READ_MIC;
772 unsigned IOCTL_SOUND_MIXER_READ_MUTE = SOUND_MIXER_READ_MUTE;
773 unsigned IOCTL_SOUND_MIXER_READ_OGAIN = SOUND_MIXER_READ_OGAIN;
774 unsigned IOCTL_SOUND_MIXER_READ_PCM = SOUND_MIXER_READ_PCM;
775 unsigned IOCTL_SOUND_MIXER_READ_RECLEV = SOUND_MIXER_READ_RECLEV;
776 unsigned IOCTL_SOUND_MIXER_READ_RECMASK = SOUND_MIXER_READ_RECMASK;
777 unsigned IOCTL_SOUND_MIXER_READ_RECSRC = SOUND_MIXER_READ_RECSRC;
778 unsigned IOCTL_SOUND_MIXER_READ_SPEAKER = SOUND_MIXER_READ_SPEAKER;
779 unsigned IOCTL_SOUND_MIXER_READ_STEREODEVS = SOUND_MIXER_READ_STEREODEVS;
780 unsigned IOCTL_SOUND_MIXER_READ_SYNTH = SOUND_MIXER_READ_SYNTH;
781 unsigned IOCTL_SOUND_MIXER_READ_TREBLE = SOUND_MIXER_READ_TREBLE;
782 unsigned IOCTL_SOUND_MIXER_READ_VOLUME = SOUND_MIXER_READ_VOLUME;
783 unsigned IOCTL_SOUND_MIXER_WRITE_ALTPCM = SOUND_MIXER_WRITE_ALTPCM;
784 unsigned IOCTL_SOUND_MIXER_WRITE_BASS = SOUND_MIXER_WRITE_BASS;
785 unsigned IOCTL_SOUND_MIXER_WRITE_CD = SOUND_MIXER_WRITE_CD;
786 unsigned IOCTL_SOUND_MIXER_WRITE_ENHANCE = SOUND_MIXER_WRITE_ENHANCE;
787 unsigned IOCTL_SOUND_MIXER_WRITE_IGAIN = SOUND_MIXER_WRITE_IGAIN;
788 unsigned IOCTL_SOUND_MIXER_WRITE_IMIX = SOUND_MIXER_WRITE_IMIX;
789 unsigned IOCTL_SOUND_MIXER_WRITE_LINE = SOUND_MIXER_WRITE_LINE;
790 unsigned IOCTL_SOUND_MIXER_WRITE_LINE1 = SOUND_MIXER_WRITE_LINE1;
791 unsigned IOCTL_SOUND_MIXER_WRITE_LINE2 = SOUND_MIXER_WRITE_LINE2;
792 unsigned IOCTL_SOUND_MIXER_WRITE_LINE3 = SOUND_MIXER_WRITE_LINE3;
793 unsigned IOCTL_SOUND_MIXER_WRITE_LOUD = SOUND_MIXER_WRITE_LOUD;
794 unsigned IOCTL_SOUND_MIXER_WRITE_MIC = SOUND_MIXER_WRITE_MIC;
795 unsigned IOCTL_SOUND_MIXER_WRITE_MUTE = SOUND_MIXER_WRITE_MUTE;
796 unsigned IOCTL_SOUND_MIXER_WRITE_OGAIN = SOUND_MIXER_WRITE_OGAIN;
797 unsigned IOCTL_SOUND_MIXER_WRITE_PCM = SOUND_MIXER_WRITE_PCM;
798 unsigned IOCTL_SOUND_MIXER_WRITE_RECLEV = SOUND_MIXER_WRITE_RECLEV;
799 unsigned IOCTL_SOUND_MIXER_WRITE_RECSRC = SOUND_MIXER_WRITE_RECSRC;
800 unsigned IOCTL_SOUND_MIXER_WRITE_SPEAKER = SOUND_MIXER_WRITE_SPEAKER;
801 unsigned IOCTL_SOUND_MIXER_WRITE_SYNTH = SOUND_MIXER_WRITE_SYNTH;
802 unsigned IOCTL_SOUND_MIXER_WRITE_TREBLE = SOUND_MIXER_WRITE_TREBLE;
803 unsigned IOCTL_SOUND_MIXER_WRITE_VOLUME = SOUND_MIXER_WRITE_VOLUME;
804 unsigned IOCTL_VT_ACTIVATE = VT_ACTIVATE;
805 unsigned IOCTL_VT_GETMODE = VT_GETMODE;
806 unsigned IOCTL_VT_OPENQRY = VT_OPENQRY;
807 unsigned IOCTL_VT_RELDISP = VT_RELDISP;
808 unsigned IOCTL_VT_SETMODE = VT_SETMODE;
809 unsigned IOCTL_VT_WAITACTIVE = VT_WAITACTIVE;
810#endif // SANITIZER_LINUX
811
812#if SANITIZER_LINUX && !SANITIZER_ANDROID
813 unsigned IOCTL_CYGETDEFTHRESH = CYGETDEFTHRESH;
814 unsigned IOCTL_CYGETDEFTIMEOUT = CYGETDEFTIMEOUT;
815 unsigned IOCTL_CYGETMON = CYGETMON;
816 unsigned IOCTL_CYGETTHRESH = CYGETTHRESH;
817 unsigned IOCTL_CYGETTIMEOUT = CYGETTIMEOUT;
818 unsigned IOCTL_CYSETDEFTHRESH = CYSETDEFTHRESH;
819 unsigned IOCTL_CYSETDEFTIMEOUT = CYSETDEFTIMEOUT;
820 unsigned IOCTL_CYSETTHRESH = CYSETTHRESH;
821 unsigned IOCTL_CYSETTIMEOUT = CYSETTIMEOUT;
822 unsigned IOCTL_EQL_EMANCIPATE = EQL_EMANCIPATE;
823 unsigned IOCTL_EQL_ENSLAVE = EQL_ENSLAVE;
824 unsigned IOCTL_EQL_GETMASTRCFG = EQL_GETMASTRCFG;
825 unsigned IOCTL_EQL_GETSLAVECFG = EQL_GETSLAVECFG;
826 unsigned IOCTL_EQL_SETMASTRCFG = EQL_SETMASTRCFG;
827 unsigned IOCTL_EQL_SETSLAVECFG = EQL_SETSLAVECFG;
828#if EV_VERSION > (0x010000)
829 unsigned IOCTL_EVIOCGKEYCODE_V2 = EVIOCGKEYCODE_V2;
830 unsigned IOCTL_EVIOCGPROP = EVIOCGPROP(0);
831 unsigned IOCTL_EVIOCSKEYCODE_V2 = EVIOCSKEYCODE_V2;
832#else
833 unsigned IOCTL_EVIOCGKEYCODE_V2 = IOCTL_NOT_PRESENT;
834 unsigned IOCTL_EVIOCGPROP = IOCTL_NOT_PRESENT;
835 unsigned IOCTL_EVIOCSKEYCODE_V2 = IOCTL_NOT_PRESENT;
836#endif
837 unsigned IOCTL_FS_IOC_GETFLAGS = FS_IOC_GETFLAGS;
838 unsigned IOCTL_FS_IOC_GETVERSION = FS_IOC_GETVERSION;
839 unsigned IOCTL_FS_IOC_SETFLAGS = FS_IOC_SETFLAGS;
840 unsigned IOCTL_FS_IOC_SETVERSION = FS_IOC_SETVERSION;
841 unsigned IOCTL_GIO_CMAP = GIO_CMAP;
842 unsigned IOCTL_GIO_FONT = GIO_FONT;
843 unsigned IOCTL_GIO_UNIMAP = GIO_UNIMAP;
844 unsigned IOCTL_GIO_UNISCRNMAP = GIO_UNISCRNMAP;
845 unsigned IOCTL_KDADDIO = KDADDIO;
846 unsigned IOCTL_KDDELIO = KDDELIO;
847 unsigned IOCTL_KDGETKEYCODE = KDGETKEYCODE;
848 unsigned IOCTL_KDGKBDIACR = KDGKBDIACR;
849 unsigned IOCTL_KDGKBENT = KDGKBENT;
850 unsigned IOCTL_KDGKBLED = KDGKBLED;
851 unsigned IOCTL_KDGKBMETA = KDGKBMETA;
852 unsigned IOCTL_KDGKBSENT = KDGKBSENT;
853 unsigned IOCTL_KDMAPDISP = KDMAPDISP;
854 unsigned IOCTL_KDSETKEYCODE = KDSETKEYCODE;
855 unsigned IOCTL_KDSIGACCEPT = KDSIGACCEPT;
856 unsigned IOCTL_KDSKBDIACR = KDSKBDIACR;
857 unsigned IOCTL_KDSKBENT = KDSKBENT;
858 unsigned IOCTL_KDSKBLED = KDSKBLED;
859 unsigned IOCTL_KDSKBMETA = KDSKBMETA;
860 unsigned IOCTL_KDSKBSENT = KDSKBSENT;
861 unsigned IOCTL_KDUNMAPDISP = KDUNMAPDISP;
862 unsigned IOCTL_LPABORT = LPABORT;
863 unsigned IOCTL_LPABORTOPEN = LPABORTOPEN;
864 unsigned IOCTL_LPCAREFUL = LPCAREFUL;
865 unsigned IOCTL_LPCHAR = LPCHAR;
866 unsigned IOCTL_LPGETIRQ = LPGETIRQ;
867 unsigned IOCTL_LPGETSTATUS = LPGETSTATUS;
868 unsigned IOCTL_LPRESET = LPRESET;
869 unsigned IOCTL_LPSETIRQ = LPSETIRQ;
870 unsigned IOCTL_LPTIME = LPTIME;
871 unsigned IOCTL_LPWAIT = LPWAIT;
872 unsigned IOCTL_MTIOCGETCONFIG = MTIOCGETCONFIG;
873 unsigned IOCTL_MTIOCSETCONFIG = MTIOCSETCONFIG;
874 unsigned IOCTL_PIO_CMAP = PIO_CMAP;
875 unsigned IOCTL_PIO_FONT = PIO_FONT;
876 unsigned IOCTL_PIO_UNIMAP = PIO_UNIMAP;
877 unsigned IOCTL_PIO_UNIMAPCLR = PIO_UNIMAPCLR;
878 unsigned IOCTL_PIO_UNISCRNMAP = PIO_UNISCRNMAP;
879 unsigned IOCTL_SCSI_IOCTL_GET_IDLUN = SCSI_IOCTL_GET_IDLUN;
880 unsigned IOCTL_SCSI_IOCTL_PROBE_HOST = SCSI_IOCTL_PROBE_HOST;
881 unsigned IOCTL_SCSI_IOCTL_TAGGED_DISABLE = SCSI_IOCTL_TAGGED_DISABLE;
882 unsigned IOCTL_SCSI_IOCTL_TAGGED_ENABLE = SCSI_IOCTL_TAGGED_ENABLE;
883 unsigned IOCTL_SIOCAIPXITFCRT = SIOCAIPXITFCRT;
884 unsigned IOCTL_SIOCAIPXPRISLT = SIOCAIPXPRISLT;
885 unsigned IOCTL_SIOCAX25ADDUID = SIOCAX25ADDUID;
886 unsigned IOCTL_SIOCAX25DELUID = SIOCAX25DELUID;
887 unsigned IOCTL_SIOCAX25GETPARMS = SIOCAX25GETPARMS;
888 unsigned IOCTL_SIOCAX25GETUID = SIOCAX25GETUID;
889 unsigned IOCTL_SIOCAX25NOUID = SIOCAX25NOUID;
890 unsigned IOCTL_SIOCAX25SETPARMS = SIOCAX25SETPARMS;
891 unsigned IOCTL_SIOCDEVPLIP = SIOCDEVPLIP;
892 unsigned IOCTL_SIOCIPXCFGDATA = SIOCIPXCFGDATA;
893 unsigned IOCTL_SIOCNRDECOBS = SIOCNRDECOBS;
894 unsigned IOCTL_SIOCNRGETPARMS = SIOCNRGETPARMS;
895 unsigned IOCTL_SIOCNRRTCTL = SIOCNRRTCTL;
896 unsigned IOCTL_SIOCNRSETPARMS = SIOCNRSETPARMS;
897 unsigned IOCTL_TIOCGSERIAL = TIOCGSERIAL;
898 unsigned IOCTL_TIOCSERGETMULTI = TIOCSERGETMULTI;
899 unsigned IOCTL_TIOCSERSETMULTI = TIOCSERSETMULTI;
900 unsigned IOCTL_TIOCSSERIAL = TIOCSSERIAL;
901#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
902
903#if SANITIZER_LINUX && !SANITIZER_ANDROID
904 unsigned IOCTL_GIO_SCRNMAP = GIO_SCRNMAP;
905 unsigned IOCTL_KDDISABIO = KDDISABIO;
906 unsigned IOCTL_KDENABIO = KDENABIO;
907 unsigned IOCTL_KDGETLED = KDGETLED;
908 unsigned IOCTL_KDGETMODE = KDGETMODE;
909 unsigned IOCTL_KDGKBMODE = KDGKBMODE;
910 unsigned IOCTL_KDGKBTYPE = KDGKBTYPE;
911 unsigned IOCTL_KDMKTONE = KDMKTONE;
912 unsigned IOCTL_KDSETLED = KDSETLED;
913 unsigned IOCTL_KDSETMODE = KDSETMODE;
914 unsigned IOCTL_KDSKBMODE = KDSKBMODE;
915 unsigned IOCTL_KIOCSOUND = KIOCSOUND;
916 unsigned IOCTL_PIO_SCRNMAP = PIO_SCRNMAP;
917 unsigned IOCTL_SNDCTL_DSP_GETISPACE = SNDCTL_DSP_GETISPACE;
918 unsigned IOCTL_SNDCTL_DSP_GETOSPACE = SNDCTL_DSP_GETOSPACE;
919#endif // (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID
920
921 const int si_SEGV_MAPERR = SEGV_MAPERR;
922 const int si_SEGV_ACCERR = SEGV_ACCERR;
923} // namespace __sanitizer
924
925using namespace __sanitizer;
926
927COMPILER_CHECK(sizeof(__sanitizer_pthread_attr_t) >= sizeof(pthread_attr_t));
928
929COMPILER_CHECK(sizeof(socklen_t) == sizeof(unsigned));
930CHECK_TYPE_SIZE(pthread_key_t);
931
932#if SANITIZER_LINUX
933// FIXME: We define those on Linux and Mac, but only check on Linux.
934COMPILER_CHECK(IOC_NRBITS == _IOC_NRBITS);
935COMPILER_CHECK(IOC_TYPEBITS == _IOC_TYPEBITS);
936COMPILER_CHECK(IOC_SIZEBITS == _IOC_SIZEBITS);
937COMPILER_CHECK(IOC_DIRBITS == _IOC_DIRBITS);
938COMPILER_CHECK(IOC_NRMASK == _IOC_NRMASK);
939COMPILER_CHECK(IOC_TYPEMASK == _IOC_TYPEMASK);
940COMPILER_CHECK(IOC_SIZEMASK == _IOC_SIZEMASK);
941COMPILER_CHECK(IOC_DIRMASK == _IOC_DIRMASK);
942COMPILER_CHECK(IOC_NRSHIFT == _IOC_NRSHIFT);
943COMPILER_CHECK(IOC_TYPESHIFT == _IOC_TYPESHIFT);
944COMPILER_CHECK(IOC_SIZESHIFT == _IOC_SIZESHIFT);
945COMPILER_CHECK(IOC_DIRSHIFT == _IOC_DIRSHIFT);
946COMPILER_CHECK(IOC_NONE == _IOC_NONE);
947COMPILER_CHECK(IOC_WRITE == _IOC_WRITE);
948COMPILER_CHECK(IOC_READ == _IOC_READ);
949COMPILER_CHECK(EVIOC_ABS_MAX == ABS_MAX);
950COMPILER_CHECK(EVIOC_EV_MAX == EV_MAX);
951COMPILER_CHECK(IOC_SIZE(0x12345678) == _IOC_SIZE(0x12345678));
952COMPILER_CHECK(IOC_DIR(0x12345678) == _IOC_DIR(0x12345678));
953COMPILER_CHECK(IOC_NR(0x12345678) == _IOC_NR(0x12345678));
954COMPILER_CHECK(IOC_TYPE(0x12345678) == _IOC_TYPE(0x12345678));
955#endif // SANITIZER_LINUX
956
957#if SANITIZER_LINUX || SANITIZER_FREEBSD
958// There are more undocumented fields in dl_phdr_info that we are not interested
959// in.
960COMPILER_CHECK(sizeof(__sanitizer_dl_phdr_info) <= sizeof(dl_phdr_info));
961CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_addr);
962CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_name);
963CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_phdr);
964CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_phnum);
965#endif // SANITIZER_LINUX || SANITIZER_FREEBSD
966
967#if (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID
968CHECK_TYPE_SIZE(glob_t);
969CHECK_SIZE_AND_OFFSET(glob_t, gl_pathc);
970CHECK_SIZE_AND_OFFSET(glob_t, gl_pathv);
971CHECK_SIZE_AND_OFFSET(glob_t, gl_offs);
972CHECK_SIZE_AND_OFFSET(glob_t, gl_flags);
973CHECK_SIZE_AND_OFFSET(glob_t, gl_closedir);
974CHECK_SIZE_AND_OFFSET(glob_t, gl_readdir);
975CHECK_SIZE_AND_OFFSET(glob_t, gl_opendir);
976CHECK_SIZE_AND_OFFSET(glob_t, gl_lstat);
977CHECK_SIZE_AND_OFFSET(glob_t, gl_stat);
978#endif
979
980CHECK_TYPE_SIZE(addrinfo);
981CHECK_SIZE_AND_OFFSET(addrinfo, ai_flags);
982CHECK_SIZE_AND_OFFSET(addrinfo, ai_family);
983CHECK_SIZE_AND_OFFSET(addrinfo, ai_socktype);
984CHECK_SIZE_AND_OFFSET(addrinfo, ai_protocol);
985CHECK_SIZE_AND_OFFSET(addrinfo, ai_protocol);
986CHECK_SIZE_AND_OFFSET(addrinfo, ai_addrlen);
987CHECK_SIZE_AND_OFFSET(addrinfo, ai_canonname);
988CHECK_SIZE_AND_OFFSET(addrinfo, ai_addr);
989
990CHECK_TYPE_SIZE(hostent);
991CHECK_SIZE_AND_OFFSET(hostent, h_name);
992CHECK_SIZE_AND_OFFSET(hostent, h_aliases);
993CHECK_SIZE_AND_OFFSET(hostent, h_addrtype);
994CHECK_SIZE_AND_OFFSET(hostent, h_length);
995CHECK_SIZE_AND_OFFSET(hostent, h_addr_list);
996
997CHECK_TYPE_SIZE(iovec);
998CHECK_SIZE_AND_OFFSET(iovec, iov_base);
999CHECK_SIZE_AND_OFFSET(iovec, iov_len);
1000
1001CHECK_TYPE_SIZE(msghdr);
1002CHECK_SIZE_AND_OFFSET(msghdr, msg_name);
1003CHECK_SIZE_AND_OFFSET(msghdr, msg_namelen);
1004CHECK_SIZE_AND_OFFSET(msghdr, msg_iov);
1005CHECK_SIZE_AND_OFFSET(msghdr, msg_iovlen);
1006CHECK_SIZE_AND_OFFSET(msghdr, msg_control);
1007CHECK_SIZE_AND_OFFSET(msghdr, msg_controllen);
1008CHECK_SIZE_AND_OFFSET(msghdr, msg_flags);
1009
1010CHECK_TYPE_SIZE(cmsghdr);
1011CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_len);
1012CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_level);
1013CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_type);
1014
1015#if SANITIZER_LINUX && (__ANDROID_API__ >= 21 || __GLIBC_PREREQ (2, 14))
1016CHECK_TYPE_SIZE(mmsghdr);
1017CHECK_SIZE_AND_OFFSET(mmsghdr, msg_hdr);
1018CHECK_SIZE_AND_OFFSET(mmsghdr, msg_len);
1019#endif
1020
1021COMPILER_CHECK(sizeof(__sanitizer_dirent) <= sizeof(dirent));
1022CHECK_SIZE_AND_OFFSET(dirent, d_ino);
1023#if SANITIZER_MAC
1024CHECK_SIZE_AND_OFFSET(dirent, d_seekoff);
1025#elif SANITIZER_FREEBSD
1026// There is no 'd_off' field on FreeBSD.
1027#else
1028CHECK_SIZE_AND_OFFSET(dirent, d_off);
1029#endif
1030CHECK_SIZE_AND_OFFSET(dirent, d_reclen);
1031
1032#if SANITIZER_LINUX && !SANITIZER_ANDROID
1033COMPILER_CHECK(sizeof(__sanitizer_dirent64) <= sizeof(dirent64));
1034CHECK_SIZE_AND_OFFSET(dirent64, d_ino);
1035CHECK_SIZE_AND_OFFSET(dirent64, d_off);
1036CHECK_SIZE_AND_OFFSET(dirent64, d_reclen);
1037#endif
1038
1039CHECK_TYPE_SIZE(ifconf);
1040CHECK_SIZE_AND_OFFSET(ifconf, ifc_len);
1041CHECK_SIZE_AND_OFFSET(ifconf, ifc_ifcu);
1042
1043CHECK_TYPE_SIZE(pollfd);
1044CHECK_SIZE_AND_OFFSET(pollfd, fd);
1045CHECK_SIZE_AND_OFFSET(pollfd, events);
1046CHECK_SIZE_AND_OFFSET(pollfd, revents);
1047
1048CHECK_TYPE_SIZE(nfds_t);
1049
1050CHECK_TYPE_SIZE(sigset_t);
1051
1052COMPILER_CHECK(sizeof(__sanitizer_sigaction) == sizeof(struct sigaction));
1053// Can't write checks for sa_handler and sa_sigaction due to them being
1054// preprocessor macros.
1055CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_mask);
1056#if !defined(__s390x__) || __GLIBC_PREREQ (2, 20)
1057// On s390x glibc 2.19 and earlier sa_flags was unsigned long, and sa_resv
1058// didn't exist.
1059CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_flags);
1060#endif
1061#if SANITIZER_LINUX && (!SANITIZER_ANDROID || !SANITIZER_MIPS32)
1062CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_restorer);
1063#endif
1064
1065#if SANITIZER_LINUX
1066CHECK_TYPE_SIZE(__sysctl_args);
1067CHECK_SIZE_AND_OFFSET(__sysctl_args, name);
1068CHECK_SIZE_AND_OFFSET(__sysctl_args, nlen);
1069CHECK_SIZE_AND_OFFSET(__sysctl_args, oldval);
1070CHECK_SIZE_AND_OFFSET(__sysctl_args, oldlenp);
1071CHECK_SIZE_AND_OFFSET(__sysctl_args, newval);
1072CHECK_SIZE_AND_OFFSET(__sysctl_args, newlen);
1073
1074CHECK_TYPE_SIZE(__kernel_uid_t);
1075CHECK_TYPE_SIZE(__kernel_gid_t);
1076
1077#if SANITIZER_USES_UID16_SYSCALLS
1078CHECK_TYPE_SIZE(__kernel_old_uid_t);
1079CHECK_TYPE_SIZE(__kernel_old_gid_t);
1080#endif
1081
1082CHECK_TYPE_SIZE(__kernel_off_t);
1083CHECK_TYPE_SIZE(__kernel_loff_t);
1084CHECK_TYPE_SIZE(__kernel_fd_set);
1085#endif
1086
1087#if !SANITIZER_ANDROID
1088CHECK_TYPE_SIZE(wordexp_t);
1089CHECK_SIZE_AND_OFFSET(wordexp_t, we_wordc);
1090CHECK_SIZE_AND_OFFSET(wordexp_t, we_wordv);
1091CHECK_SIZE_AND_OFFSET(wordexp_t, we_offs);
1092#endif
1093
1094CHECK_TYPE_SIZE(tm);
1095CHECK_SIZE_AND_OFFSET(tm, tm_sec);
1096CHECK_SIZE_AND_OFFSET(tm, tm_min);
1097CHECK_SIZE_AND_OFFSET(tm, tm_hour);
1098CHECK_SIZE_AND_OFFSET(tm, tm_mday);
1099CHECK_SIZE_AND_OFFSET(tm, tm_mon);
1100CHECK_SIZE_AND_OFFSET(tm, tm_year);
1101CHECK_SIZE_AND_OFFSET(tm, tm_wday);
1102CHECK_SIZE_AND_OFFSET(tm, tm_yday);
1103CHECK_SIZE_AND_OFFSET(tm, tm_isdst);
1104CHECK_SIZE_AND_OFFSET(tm, tm_gmtoff);
1105CHECK_SIZE_AND_OFFSET(tm, tm_zone);
1106
1107#if SANITIZER_LINUX
1108CHECK_TYPE_SIZE(mntent);
1109CHECK_SIZE_AND_OFFSET(mntent, mnt_fsname);
1110CHECK_SIZE_AND_OFFSET(mntent, mnt_dir);
1111CHECK_SIZE_AND_OFFSET(mntent, mnt_type);
1112CHECK_SIZE_AND_OFFSET(mntent, mnt_opts);
1113CHECK_SIZE_AND_OFFSET(mntent, mnt_freq);
1114CHECK_SIZE_AND_OFFSET(mntent, mnt_passno);
1115#endif
1116
1117CHECK_TYPE_SIZE(ether_addr);
1118
1119#if (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID
1120CHECK_TYPE_SIZE(ipc_perm);
1121# if SANITIZER_FREEBSD
1122CHECK_SIZE_AND_OFFSET(ipc_perm, key);
1123CHECK_SIZE_AND_OFFSET(ipc_perm, seq);
1124# else
1125CHECK_SIZE_AND_OFFSET(ipc_perm, __key);
1126CHECK_SIZE_AND_OFFSET(ipc_perm, __seq);
1127# endif
1128CHECK_SIZE_AND_OFFSET(ipc_perm, uid);
1129CHECK_SIZE_AND_OFFSET(ipc_perm, gid);
1130CHECK_SIZE_AND_OFFSET(ipc_perm, cuid);
1131CHECK_SIZE_AND_OFFSET(ipc_perm, cgid);
1132#if !SANITIZER_LINUX || __GLIBC_PREREQ (2, 31)
1133/* glibc 2.30 and earlier provided 16-bit mode field instead of 32-bit
1134 on many architectures. */
1135CHECK_SIZE_AND_OFFSET(ipc_perm, mode);
1136#endif
1137
1138CHECK_TYPE_SIZE(shmid_ds);
1139CHECK_SIZE_AND_OFFSET(shmid_ds, shm_perm);
1140CHECK_SIZE_AND_OFFSET(shmid_ds, shm_segsz);
1141CHECK_SIZE_AND_OFFSET(shmid_ds, shm_atime);
1142CHECK_SIZE_AND_OFFSET(shmid_ds, shm_dtime);
1143CHECK_SIZE_AND_OFFSET(shmid_ds, shm_ctime);
1144CHECK_SIZE_AND_OFFSET(shmid_ds, shm_cpid);
1145CHECK_SIZE_AND_OFFSET(shmid_ds, shm_lpid);
1146CHECK_SIZE_AND_OFFSET(shmid_ds, shm_nattch);
1147#endif
1148
1149CHECK_TYPE_SIZE(clock_t);
1150
1151#if SANITIZER_LINUX
1152CHECK_TYPE_SIZE(clockid_t);
1153#endif
1154
1155#if !SANITIZER_ANDROID
1156CHECK_TYPE_SIZE(ifaddrs);
1157CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_next);
1158CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_name);
1159CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_addr);
1160CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_netmask);
1161#if SANITIZER_LINUX || SANITIZER_FREEBSD
1162// Compare against the union, because we can't reach into the union in a
1163// compliant way.
1164#ifdef ifa_dstaddr
1165#undef ifa_dstaddr
1166#endif
1167# if SANITIZER_FREEBSD
1168CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_dstaddr);
1169# else
1170COMPILER_CHECK(sizeof(((__sanitizer_ifaddrs *)nullptr)->ifa_dstaddr) ==
1171 sizeof(((ifaddrs *)nullptr)->ifa_ifu));
1172COMPILER_CHECK(offsetof(__sanitizer_ifaddrs, ifa_dstaddr) ==
1173 offsetof(ifaddrs, ifa_ifu));
1174# endif // SANITIZER_FREEBSD
1175#else
1176CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_dstaddr);
1177#endif // SANITIZER_LINUX
1178CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_data);
1179#endif
1180
1181#if SANITIZER_LINUX
1182COMPILER_CHECK(sizeof(__sanitizer_struct_mallinfo) == sizeof(struct mallinfo));
1183#endif
1184
1185#if !SANITIZER_ANDROID
1186CHECK_TYPE_SIZE(timeb);
1187CHECK_SIZE_AND_OFFSET(timeb, time);
1188CHECK_SIZE_AND_OFFSET(timeb, millitm);
1189CHECK_SIZE_AND_OFFSET(timeb, timezone);
1190CHECK_SIZE_AND_OFFSET(timeb, dstflag);
1191#endif
1192
1193CHECK_TYPE_SIZE(passwd);
1194CHECK_SIZE_AND_OFFSET(passwd, pw_name);
1195CHECK_SIZE_AND_OFFSET(passwd, pw_passwd);
1196CHECK_SIZE_AND_OFFSET(passwd, pw_uid);
1197CHECK_SIZE_AND_OFFSET(passwd, pw_gid);
1198CHECK_SIZE_AND_OFFSET(passwd, pw_dir);
1199CHECK_SIZE_AND_OFFSET(passwd, pw_shell);
1200
1201#if !SANITIZER_ANDROID
1202CHECK_SIZE_AND_OFFSET(passwd, pw_gecos);
1203#endif
1204
1205#if SANITIZER_MAC
1206CHECK_SIZE_AND_OFFSET(passwd, pw_change);
1207CHECK_SIZE_AND_OFFSET(passwd, pw_expire);
1208CHECK_SIZE_AND_OFFSET(passwd, pw_class);
1209#endif
1210
1211
1212CHECK_TYPE_SIZE(group);
1213CHECK_SIZE_AND_OFFSET(group, gr_name);
1214CHECK_SIZE_AND_OFFSET(group, gr_passwd);
1215CHECK_SIZE_AND_OFFSET(group, gr_gid);
1216CHECK_SIZE_AND_OFFSET(group, gr_mem);
1217
1218#if HAVE_RPC_XDR_H
1219CHECK_TYPE_SIZE(XDR);
1220CHECK_SIZE_AND_OFFSET(XDR, x_op);
1221CHECK_SIZE_AND_OFFSET(XDR, x_ops);
1222CHECK_SIZE_AND_OFFSET(XDR, x_public);
1223CHECK_SIZE_AND_OFFSET(XDR, x_private);
1224CHECK_SIZE_AND_OFFSET(XDR, x_base);
1225CHECK_SIZE_AND_OFFSET(XDR, x_handy);
1226COMPILER_CHECK(__sanitizer_XDR_ENCODE == XDR_ENCODE);
1227COMPILER_CHECK(__sanitizer_XDR_DECODE == XDR_DECODE);
1228COMPILER_CHECK(__sanitizer_XDR_FREE == XDR_FREE);
1229#endif
1230
1231#if SANITIZER_LINUX && !SANITIZER_ANDROID
1232COMPILER_CHECK(sizeof(__sanitizer_FILE) <= sizeof(FILE));
1233CHECK_SIZE_AND_OFFSET(FILE, _flags);
1234CHECK_SIZE_AND_OFFSET(FILE, _IO_read_ptr);
1235CHECK_SIZE_AND_OFFSET(FILE, _IO_read_end);
1236CHECK_SIZE_AND_OFFSET(FILE, _IO_read_base);
1237CHECK_SIZE_AND_OFFSET(FILE, _IO_write_ptr);
1238CHECK_SIZE_AND_OFFSET(FILE, _IO_write_end);
1239CHECK_SIZE_AND_OFFSET(FILE, _IO_write_base);
1240CHECK_SIZE_AND_OFFSET(FILE, _IO_buf_base);
1241CHECK_SIZE_AND_OFFSET(FILE, _IO_buf_end);
1242CHECK_SIZE_AND_OFFSET(FILE, _IO_save_base);
1243CHECK_SIZE_AND_OFFSET(FILE, _IO_backup_base);
1244CHECK_SIZE_AND_OFFSET(FILE, _IO_save_end);
1245CHECK_SIZE_AND_OFFSET(FILE, _markers);
1246CHECK_SIZE_AND_OFFSET(FILE, _chain);
1247CHECK_SIZE_AND_OFFSET(FILE, _fileno);
1248#endif
1249
1250#if SANITIZER_LINUX && !SANITIZER_ANDROID
1251COMPILER_CHECK(sizeof(__sanitizer__obstack_chunk) <= sizeof(_obstack_chunk));
1252CHECK_SIZE_AND_OFFSET(_obstack_chunk, limit);
1253CHECK_SIZE_AND_OFFSET(_obstack_chunk, prev);
1254CHECK_TYPE_SIZE(obstack);
1255CHECK_SIZE_AND_OFFSET(obstack, chunk_size);
1256CHECK_SIZE_AND_OFFSET(obstack, chunk);
1257CHECK_SIZE_AND_OFFSET(obstack, object_base);
1258CHECK_SIZE_AND_OFFSET(obstack, next_free);
1259
1260CHECK_TYPE_SIZE(cookie_io_functions_t);
1261CHECK_SIZE_AND_OFFSET(cookie_io_functions_t, read);
1262CHECK_SIZE_AND_OFFSET(cookie_io_functions_t, write);
1263CHECK_SIZE_AND_OFFSET(cookie_io_functions_t, seek);
1264CHECK_SIZE_AND_OFFSET(cookie_io_functions_t, close);
1265#endif
1266
1267#if SANITIZER_LINUX || SANITIZER_FREEBSD
1268CHECK_TYPE_SIZE(sem_t);
1269#endif
1270
1271#if SANITIZER_LINUX && defined(__arm__)
1272COMPILER_CHECK(ARM_VFPREGS_SIZE == ARM_VFPREGS_SIZE_ASAN);
1273#endif
1274
1275#endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_MAC
lib/tsan/sanitizer_common/sanitizer_platform_limits_posix.h created+1453
...@@ -0,0 +1,1453 @@
1//===-- sanitizer_platform_limits_posix.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// Sizes and layouts of platform-specific POSIX data structures.
12//===----------------------------------------------------------------------===//
13
14#ifndef SANITIZER_PLATFORM_LIMITS_POSIX_H
15#define SANITIZER_PLATFORM_LIMITS_POSIX_H
16
17#if SANITIZER_LINUX || SANITIZER_MAC
18
19#include "sanitizer_internal_defs.h"
20#include "sanitizer_platform.h"
21
22#if defined(__sparc__)
23// FIXME: This can't be included from tsan which does not support sparc yet.
24#include "sanitizer_glibc_version.h"
25#endif
26
27# define GET_LINK_MAP_BY_DLOPEN_HANDLE(handle) ((link_map*)(handle))
28
29namespace __sanitizer {
30extern unsigned struct_utsname_sz;
31extern unsigned struct_stat_sz;
32#if !SANITIZER_IOS
33extern unsigned struct_stat64_sz;
34#endif
35extern unsigned struct_rusage_sz;
36extern unsigned siginfo_t_sz;
37extern unsigned struct_itimerval_sz;
38extern unsigned pthread_t_sz;
39extern unsigned pthread_mutex_t_sz;
40extern unsigned pthread_cond_t_sz;
41extern unsigned pid_t_sz;
42extern unsigned timeval_sz;
43extern unsigned uid_t_sz;
44extern unsigned gid_t_sz;
45extern unsigned mbstate_t_sz;
46extern unsigned struct_timezone_sz;
47extern unsigned struct_tms_sz;
48extern unsigned struct_itimerspec_sz;
49extern unsigned struct_sigevent_sz;
50extern unsigned struct_stack_t_sz;
51extern unsigned struct_sched_param_sz;
52extern unsigned struct_statfs64_sz;
53extern unsigned struct_regex_sz;
54extern unsigned struct_regmatch_sz;
55
56#if !SANITIZER_ANDROID
57extern unsigned struct_fstab_sz;
58extern unsigned struct_statfs_sz;
59extern unsigned struct_sockaddr_sz;
60extern unsigned ucontext_t_sz;
61#endif // !SANITIZER_ANDROID
62
63#if SANITIZER_LINUX
64
65#if defined(__x86_64__)
66const unsigned struct_kernel_stat_sz = 144;
67const unsigned struct_kernel_stat64_sz = 0;
68#elif defined(__i386__)
69const unsigned struct_kernel_stat_sz = 64;
70const unsigned struct_kernel_stat64_sz = 96;
71#elif defined(__arm__)
72const unsigned struct_kernel_stat_sz = 64;
73const unsigned struct_kernel_stat64_sz = 104;
74#elif defined(__aarch64__)
75const unsigned struct_kernel_stat_sz = 128;
76const unsigned struct_kernel_stat64_sz = 104;
77#elif defined(__powerpc__) && !defined(__powerpc64__)
78const unsigned struct_kernel_stat_sz = 72;
79const unsigned struct_kernel_stat64_sz = 104;
80#elif defined(__powerpc64__)
81const unsigned struct_kernel_stat_sz = 144;
82const unsigned struct_kernel_stat64_sz = 104;
83#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);
87const unsigned struct_kernel_stat64_sz = 104;
88#elif defined(__s390__) && !defined(__s390x__)
89const unsigned struct_kernel_stat_sz = 64;
90const unsigned struct_kernel_stat64_sz = 104;
91#elif defined(__s390x__)
92const unsigned struct_kernel_stat_sz = 144;
93const unsigned struct_kernel_stat64_sz = 0;
94#elif defined(__sparc__) && defined(__arch64__)
95const unsigned struct___old_kernel_stat_sz = 0;
96const unsigned struct_kernel_stat_sz = 104;
97const unsigned struct_kernel_stat64_sz = 144;
98#elif defined(__sparc__) && !defined(__arch64__)
99const unsigned struct___old_kernel_stat_sz = 0;
100const unsigned struct_kernel_stat_sz = 64;
101const unsigned struct_kernel_stat64_sz = 104;
102#elif defined(__riscv) && __riscv_xlen == 64
103const unsigned struct_kernel_stat_sz = 128;
104const unsigned struct_kernel_stat64_sz = 104;
105#endif
106struct __sanitizer_perf_event_attr {
107 unsigned type;
108 unsigned size;
109 // More fields that vary with the kernel version.
110};
111
112extern unsigned struct_epoll_event_sz;
113extern unsigned struct_sysinfo_sz;
114extern unsigned __user_cap_header_struct_sz;
115extern unsigned __user_cap_data_struct_sz;
116extern unsigned struct_new_utsname_sz;
117extern unsigned struct_old_utsname_sz;
118extern unsigned struct_oldold_utsname_sz;
119
120const unsigned struct_kexec_segment_sz = 4 * sizeof(unsigned long);
121#endif // SANITIZER_LINUX
122
123#if SANITIZER_LINUX
124
125#if defined(__powerpc64__) || defined(__s390__)
126const unsigned struct___old_kernel_stat_sz = 0;
127#elif !defined(__sparc__)
128const unsigned struct___old_kernel_stat_sz = 32;
129#endif
130
131extern unsigned struct_rlimit_sz;
132extern unsigned struct_utimbuf_sz;
133extern unsigned struct_timespec_sz;
134
135struct __sanitizer_iocb {
136 u64 aio_data;
137 u32 aio_key_or_aio_reserved1; // Simply crazy.
138 u32 aio_reserved1_or_aio_key; // Luckily, we don't need these.
139 u16 aio_lio_opcode;
140 s16 aio_reqprio;
141 u32 aio_fildes;
142 u64 aio_buf;
143 u64 aio_nbytes;
144 s64 aio_offset;
145 u64 aio_reserved2;
146 u64 aio_reserved3;
147};
148
149struct __sanitizer_io_event {
150 u64 data;
151 u64 obj;
152 u64 res;
153 u64 res2;
154};
155
156const unsigned iocb_cmd_pread = 0;
157const unsigned iocb_cmd_pwrite = 1;
158const unsigned iocb_cmd_preadv = 7;
159const unsigned iocb_cmd_pwritev = 8;
160
161struct __sanitizer___sysctl_args {
162 int *name;
163 int nlen;
164 void *oldval;
165 uptr *oldlenp;
166 void *newval;
167 uptr newlen;
168 unsigned long ___unused[4];
169};
170
171const unsigned old_sigset_t_sz = sizeof(unsigned long);
172
173struct __sanitizer_sem_t {
174#if SANITIZER_ANDROID && defined(_LP64)
175 int data[4];
176#elif SANITIZER_ANDROID && !defined(_LP64)
177 int data;
178#elif SANITIZER_LINUX
179 uptr data[4];
180#endif
181};
182#endif // SANITIZER_LINUX
183
184#if SANITIZER_ANDROID
185struct __sanitizer_struct_mallinfo {
186 uptr v[10];
187};
188#endif
189
190#if SANITIZER_LINUX && !SANITIZER_ANDROID
191struct __sanitizer_struct_mallinfo {
192 int v[10];
193};
194
195extern unsigned struct_ustat_sz;
196extern unsigned struct_rlimit64_sz;
197extern unsigned struct_statvfs64_sz;
198
199struct __sanitizer_ipc_perm {
200 int __key;
201 int uid;
202 int gid;
203 int cuid;
204 int cgid;
205#ifdef __powerpc__
206 unsigned mode;
207 unsigned __seq;
208 u64 __unused1;
209 u64 __unused2;
210#elif defined(__sparc__)
211 unsigned mode;
212 unsigned short __pad2;
213 unsigned short __seq;
214 unsigned long long __unused1;
215 unsigned long long __unused2;
216#else
217 unsigned int mode;
218 unsigned short __seq;
219 unsigned short __pad2;
220#if defined(__x86_64__) && !defined(_LP64)
221 u64 __unused1;
222 u64 __unused2;
223#else
224 unsigned long __unused1;
225 unsigned long __unused2;
226#endif
227#endif
228};
229
230struct __sanitizer_shmid_ds {
231 __sanitizer_ipc_perm shm_perm;
232#if defined(__sparc__)
233#if !defined(__arch64__)
234 u32 __pad1;
235#endif
236 long shm_atime;
237#if !defined(__arch64__)
238 u32 __pad2;
239#endif
240 long shm_dtime;
241#if !defined(__arch64__)
242 u32 __pad3;
243#endif
244 long shm_ctime;
245 uptr shm_segsz;
246 int shm_cpid;
247 int shm_lpid;
248 unsigned long shm_nattch;
249 unsigned long __glibc_reserved1;
250 unsigned long __glibc_reserved2;
251#else
252#ifndef __powerpc__
253 uptr shm_segsz;
254#elif !defined(__powerpc64__)
255 uptr __unused0;
256#endif
257#if defined(__x86_64__) && !defined(_LP64)
258 u64 shm_atime;
259 u64 shm_dtime;
260 u64 shm_ctime;
261#else
262 uptr shm_atime;
263#if !defined(_LP64) && !defined(__mips__)
264 uptr __unused1;
265#endif
266 uptr shm_dtime;
267#if !defined(_LP64) && !defined(__mips__)
268 uptr __unused2;
269#endif
270 uptr shm_ctime;
271#if !defined(_LP64) && !defined(__mips__)
272 uptr __unused3;
273#endif
274#endif
275#ifdef __powerpc__
276 uptr shm_segsz;
277#endif
278 int shm_cpid;
279 int shm_lpid;
280#if defined(__x86_64__) && !defined(_LP64)
281 u64 shm_nattch;
282 u64 __unused4;
283 u64 __unused5;
284#else
285 uptr shm_nattch;
286 uptr __unused4;
287 uptr __unused5;
288#endif
289#endif
290};
291#endif
292
293#if SANITIZER_LINUX && !SANITIZER_ANDROID
294extern unsigned struct_msqid_ds_sz;
295extern unsigned struct_mq_attr_sz;
296extern unsigned struct_timex_sz;
297extern unsigned struct_statvfs_sz;
298extern unsigned struct_crypt_data_sz;
299#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
300
301struct __sanitizer_iovec {
302 void *iov_base;
303 uptr iov_len;
304};
305
306#if !SANITIZER_ANDROID
307struct __sanitizer_ifaddrs {
308 struct __sanitizer_ifaddrs *ifa_next;
309 char *ifa_name;
310 unsigned int ifa_flags;
311 void *ifa_addr; // (struct sockaddr *)
312 void *ifa_netmask; // (struct sockaddr *)
313 // This is a union on Linux.
314# ifdef ifa_dstaddr
315# undef ifa_dstaddr
316# endif
317 void *ifa_dstaddr; // (struct sockaddr *)
318 void *ifa_data;
319};
320#endif // !SANITIZER_ANDROID
321
322#if SANITIZER_MAC
323typedef unsigned long __sanitizer_pthread_key_t;
324#else
325typedef unsigned __sanitizer_pthread_key_t;
326#endif
327
328#if SANITIZER_LINUX && !SANITIZER_ANDROID
329
330struct __sanitizer_XDR {
331 int x_op;
332 void *x_ops;
333 uptr x_public;
334 uptr x_private;
335 uptr x_base;
336 unsigned x_handy;
337};
338
339const int __sanitizer_XDR_ENCODE = 0;
340const int __sanitizer_XDR_DECODE = 1;
341const int __sanitizer_XDR_FREE = 2;
342#endif
343
344struct __sanitizer_passwd {
345 char *pw_name;
346 char *pw_passwd;
347 int pw_uid;
348 int pw_gid;
349#if SANITIZER_MAC
350 long pw_change;
351 char *pw_class;
352#endif
353#if !(SANITIZER_ANDROID && (SANITIZER_WORDSIZE == 32))
354 char *pw_gecos;
355#endif
356 char *pw_dir;
357 char *pw_shell;
358#if SANITIZER_MAC
359 long pw_expire;
360#endif
361};
362
363struct __sanitizer_group {
364 char *gr_name;
365 char *gr_passwd;
366 int gr_gid;
367 char **gr_mem;
368};
369
370#if defined(__x86_64__) && !defined(_LP64)
371typedef long long __sanitizer_time_t;
372#else
373typedef long __sanitizer_time_t;
374#endif
375
376typedef long __sanitizer_suseconds_t;
377
378struct __sanitizer_timeval {
379 __sanitizer_time_t tv_sec;
380 __sanitizer_suseconds_t tv_usec;
381};
382
383struct __sanitizer_itimerval {
384 struct __sanitizer_timeval it_interval;
385 struct __sanitizer_timeval it_value;
386};
387
388struct __sanitizer_timeb {
389 __sanitizer_time_t time;
390 unsigned short millitm;
391 short timezone;
392 short dstflag;
393};
394
395struct __sanitizer_ether_addr {
396 u8 octet[6];
397};
398
399struct __sanitizer_tm {
400 int tm_sec;
401 int tm_min;
402 int tm_hour;
403 int tm_mday;
404 int tm_mon;
405 int tm_year;
406 int tm_wday;
407 int tm_yday;
408 int tm_isdst;
409 long int tm_gmtoff;
410 const char *tm_zone;
411};
412
413#if SANITIZER_LINUX
414struct __sanitizer_mntent {
415 char *mnt_fsname;
416 char *mnt_dir;
417 char *mnt_type;
418 char *mnt_opts;
419 int mnt_freq;
420 int mnt_passno;
421};
422
423struct __sanitizer_file_handle {
424 unsigned int handle_bytes;
425 int handle_type;
426 unsigned char f_handle[1]; // variable sized
427};
428#endif
429
430#if SANITIZER_MAC
431struct __sanitizer_msghdr {
432 void *msg_name;
433 unsigned msg_namelen;
434 struct __sanitizer_iovec *msg_iov;
435 unsigned msg_iovlen;
436 void *msg_control;
437 unsigned msg_controllen;
438 int msg_flags;
439};
440struct __sanitizer_cmsghdr {
441 unsigned cmsg_len;
442 int cmsg_level;
443 int cmsg_type;
444};
445#else
446struct __sanitizer_msghdr {
447 void *msg_name;
448 unsigned msg_namelen;
449 struct __sanitizer_iovec *msg_iov;
450 uptr msg_iovlen;
451 void *msg_control;
452 uptr msg_controllen;
453 int msg_flags;
454};
455struct __sanitizer_cmsghdr {
456 uptr cmsg_len;
457 int cmsg_level;
458 int cmsg_type;
459};
460#endif
461
462#if SANITIZER_LINUX
463struct __sanitizer_mmsghdr {
464 __sanitizer_msghdr msg_hdr;
465 unsigned int msg_len;
466};
467#endif
468
469#if SANITIZER_MAC
470struct __sanitizer_dirent {
471 unsigned long long d_ino;
472 unsigned long long d_seekoff;
473 unsigned short d_reclen;
474 // more fields that we don't care about
475};
476#elif SANITIZER_ANDROID || defined(__x86_64__)
477struct __sanitizer_dirent {
478 unsigned long long d_ino;
479 unsigned long long d_off;
480 unsigned short d_reclen;
481 // more fields that we don't care about
482};
483#else
484struct __sanitizer_dirent {
485 uptr d_ino;
486 uptr d_off;
487 unsigned short d_reclen;
488 // more fields that we don't care about
489};
490#endif
491
492#if SANITIZER_LINUX && !SANITIZER_ANDROID
493struct __sanitizer_dirent64 {
494 unsigned long long d_ino;
495 unsigned long long d_off;
496 unsigned short d_reclen;
497 // more fields that we don't care about
498};
499#endif
500
501#if defined(__x86_64__) && !defined(_LP64)
502typedef long long __sanitizer_clock_t;
503#else
504typedef long __sanitizer_clock_t;
505#endif
506
507#if SANITIZER_LINUX
508typedef int __sanitizer_clockid_t;
509#endif
510
511#if SANITIZER_LINUX
512#if defined(_LP64) || defined(__x86_64__) || defined(__powerpc__) || \
513 defined(__mips__)
514typedef unsigned __sanitizer___kernel_uid_t;
515typedef unsigned __sanitizer___kernel_gid_t;
516#else
517typedef unsigned short __sanitizer___kernel_uid_t;
518typedef unsigned short __sanitizer___kernel_gid_t;
519#endif
520#if defined(__x86_64__) && !defined(_LP64)
521typedef long long __sanitizer___kernel_off_t;
522#else
523typedef long __sanitizer___kernel_off_t;
524#endif
525
526#if defined(__powerpc__) || defined(__mips__)
527typedef unsigned int __sanitizer___kernel_old_uid_t;
528typedef unsigned int __sanitizer___kernel_old_gid_t;
529#else
530typedef unsigned short __sanitizer___kernel_old_uid_t;
531typedef unsigned short __sanitizer___kernel_old_gid_t;
532#endif
533
534typedef long long __sanitizer___kernel_loff_t;
535typedef struct {
536 unsigned long fds_bits[1024 / (8 * sizeof(long))];
537} __sanitizer___kernel_fd_set;
538#endif
539
540// This thing depends on the platform. We are only interested in the upper
541// limit. Verified with a compiler assert in .cpp.
542union __sanitizer_pthread_attr_t {
543 char size[128];
544 void *align;
545};
546
547#if SANITIZER_ANDROID
548# if SANITIZER_MIPS
549typedef unsigned long __sanitizer_sigset_t[16 / sizeof(unsigned long)];
550# else
551typedef unsigned long __sanitizer_sigset_t;
552# endif
553#elif SANITIZER_MAC
554typedef unsigned __sanitizer_sigset_t;
555#elif SANITIZER_LINUX
556struct __sanitizer_sigset_t {
557 // The size is determined by looking at sizeof of real sigset_t on linux.
558 uptr val[128 / sizeof(uptr)];
559};
560#endif
561
562struct __sanitizer_siginfo {
563 // The size is determined by looking at sizeof of real siginfo_t on linux.
564 u64 opaque[128 / sizeof(u64)];
565};
566
567using __sanitizer_sighandler_ptr = void (*)(int sig);
568using __sanitizer_sigactionhandler_ptr = void (*)(int sig,
569 __sanitizer_siginfo *siginfo,
570 void *uctx);
571
572// Linux system headers define the 'sa_handler' and 'sa_sigaction' macros.
573#if SANITIZER_ANDROID && (SANITIZER_WORDSIZE == 64)
574struct __sanitizer_sigaction {
575 unsigned sa_flags;
576 union {
577 __sanitizer_sigactionhandler_ptr sigaction;
578 __sanitizer_sighandler_ptr handler;
579 };
580 __sanitizer_sigset_t sa_mask;
581 void (*sa_restorer)();
582};
583#elif SANITIZER_ANDROID && SANITIZER_MIPS32 // check this before WORDSIZE == 32
584struct __sanitizer_sigaction {
585 unsigned sa_flags;
586 union {
587 __sanitizer_sigactionhandler_ptr sigaction;
588 __sanitizer_sighandler_ptr handler;
589 };
590 __sanitizer_sigset_t sa_mask;
591};
592#elif SANITIZER_ANDROID && (SANITIZER_WORDSIZE == 32)
593struct __sanitizer_sigaction {
594 union {
595 __sanitizer_sigactionhandler_ptr sigaction;
596 __sanitizer_sighandler_ptr handler;
597 };
598 __sanitizer_sigset_t sa_mask;
599 uptr sa_flags;
600 void (*sa_restorer)();
601};
602#else // !SANITIZER_ANDROID
603struct __sanitizer_sigaction {
604#if defined(__mips__) && !SANITIZER_FREEBSD
605 unsigned int sa_flags;
606#endif
607 union {
608 __sanitizer_sigactionhandler_ptr sigaction;
609 __sanitizer_sighandler_ptr handler;
610 };
611#if SANITIZER_FREEBSD
612 int sa_flags;
613 __sanitizer_sigset_t sa_mask;
614#else
615#if defined(__s390x__)
616 int sa_resv;
617#else
618 __sanitizer_sigset_t sa_mask;
619#endif
620#ifndef __mips__
621#if defined(__sparc__)
622#if __GLIBC_PREREQ (2, 20)
623 // On sparc glibc 2.19 and earlier sa_flags was unsigned long.
624#if defined(__arch64__)
625 // To maintain ABI compatibility on sparc64 when switching to an int,
626 // __glibc_reserved0 was added.
627 int __glibc_reserved0;
628#endif
629 int sa_flags;
630#else
631 unsigned long sa_flags;
632#endif
633#else
634 int sa_flags;
635#endif
636#endif
637#endif
638#if SANITIZER_LINUX
639 void (*sa_restorer)();
640#endif
641#if defined(__mips__) && (SANITIZER_WORDSIZE == 32)
642 int sa_resv[1];
643#endif
644#if defined(__s390x__)
645 __sanitizer_sigset_t sa_mask;
646#endif
647};
648#endif // !SANITIZER_ANDROID
649
650#if defined(__mips__)
651struct __sanitizer_kernel_sigset_t {
652 uptr sig[2];
653};
654#else
655struct __sanitizer_kernel_sigset_t {
656 u8 sig[8];
657};
658#endif
659
660// Linux system headers define the 'sa_handler' and 'sa_sigaction' macros.
661#if SANITIZER_MIPS
662struct __sanitizer_kernel_sigaction_t {
663 unsigned int sa_flags;
664 union {
665 void (*handler)(int signo);
666 void (*sigaction)(int signo, __sanitizer_siginfo *info, void *ctx);
667 };
668 __sanitizer_kernel_sigset_t sa_mask;
669 void (*sa_restorer)(void);
670};
671#else
672struct __sanitizer_kernel_sigaction_t {
673 union {
674 void (*handler)(int signo);
675 void (*sigaction)(int signo, __sanitizer_siginfo *info, void *ctx);
676 };
677 unsigned long sa_flags;
678 void (*sa_restorer)(void);
679 __sanitizer_kernel_sigset_t sa_mask;
680};
681#endif
682
683extern const uptr sig_ign;
684extern const uptr sig_dfl;
685extern const uptr sig_err;
686extern const uptr sa_siginfo;
687
688#if SANITIZER_LINUX
689extern int e_tabsz;
690#endif
691
692extern int af_inet;
693extern int af_inet6;
694uptr __sanitizer_in_addr_sz(int af);
695
696#if SANITIZER_LINUX
697struct __sanitizer_dl_phdr_info {
698 uptr dlpi_addr;
699 const char *dlpi_name;
700 const void *dlpi_phdr;
701 short dlpi_phnum;
702};
703
704extern unsigned struct_ElfW_Phdr_sz;
705#endif
706
707struct __sanitizer_protoent {
708 char *p_name;
709 char **p_aliases;
710 int p_proto;
711};
712
713struct __sanitizer_addrinfo {
714 int ai_flags;
715 int ai_family;
716 int ai_socktype;
717 int ai_protocol;
718#if SANITIZER_ANDROID || SANITIZER_MAC
719 unsigned ai_addrlen;
720 char *ai_canonname;
721 void *ai_addr;
722#else // LINUX
723 unsigned ai_addrlen;
724 void *ai_addr;
725 char *ai_canonname;
726#endif
727 struct __sanitizer_addrinfo *ai_next;
728};
729
730struct __sanitizer_hostent {
731 char *h_name;
732 char **h_aliases;
733 int h_addrtype;
734 int h_length;
735 char **h_addr_list;
736};
737
738struct __sanitizer_pollfd {
739 int fd;
740 short events;
741 short revents;
742};
743
744#if SANITIZER_ANDROID || SANITIZER_MAC
745typedef unsigned __sanitizer_nfds_t;
746#else
747typedef unsigned long __sanitizer_nfds_t;
748#endif
749
750#if !SANITIZER_ANDROID
751# if SANITIZER_LINUX
752struct __sanitizer_glob_t {
753 uptr gl_pathc;
754 char **gl_pathv;
755 uptr gl_offs;
756 int gl_flags;
757
758 void (*gl_closedir)(void *dirp);
759 void *(*gl_readdir)(void *dirp);
760 void *(*gl_opendir)(const char *);
761 int (*gl_lstat)(const char *, void *);
762 int (*gl_stat)(const char *, void *);
763};
764# endif // SANITIZER_LINUX
765
766# if SANITIZER_LINUX
767extern int glob_nomatch;
768extern int glob_altdirfunc;
769# endif
770#endif // !SANITIZER_ANDROID
771
772extern unsigned path_max;
773
774struct __sanitizer_wordexp_t {
775 uptr we_wordc;
776 char **we_wordv;
777 uptr we_offs;
778};
779
780#if SANITIZER_LINUX && !SANITIZER_ANDROID
781struct __sanitizer_FILE {
782 int _flags;
783 char *_IO_read_ptr;
784 char *_IO_read_end;
785 char *_IO_read_base;
786 char *_IO_write_base;
787 char *_IO_write_ptr;
788 char *_IO_write_end;
789 char *_IO_buf_base;
790 char *_IO_buf_end;
791 char *_IO_save_base;
792 char *_IO_backup_base;
793 char *_IO_save_end;
794 void *_markers;
795 __sanitizer_FILE *_chain;
796 int _fileno;
797};
798# define SANITIZER_HAS_STRUCT_FILE 1
799#else
800typedef void __sanitizer_FILE;
801# define SANITIZER_HAS_STRUCT_FILE 0
802#endif
803
804#if SANITIZER_LINUX && !SANITIZER_ANDROID && \
805 (defined(__i386) || defined(__x86_64) || defined(__mips64) || \
806 defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \
807 defined(__s390__))
808extern unsigned struct_user_regs_struct_sz;
809extern unsigned struct_user_fpregs_struct_sz;
810extern unsigned struct_user_fpxregs_struct_sz;
811extern unsigned struct_user_vfpregs_struct_sz;
812
813extern int ptrace_peektext;
814extern int ptrace_peekdata;
815extern int ptrace_peekuser;
816extern int ptrace_getregs;
817extern int ptrace_setregs;
818extern int ptrace_getfpregs;
819extern int ptrace_setfpregs;
820extern int ptrace_getfpxregs;
821extern int ptrace_setfpxregs;
822extern int ptrace_getvfpregs;
823extern int ptrace_setvfpregs;
824extern int ptrace_getsiginfo;
825extern int ptrace_setsiginfo;
826extern int ptrace_getregset;
827extern int ptrace_setregset;
828extern int ptrace_geteventmsg;
829#endif
830
831#if SANITIZER_LINUX && !SANITIZER_ANDROID
832extern unsigned struct_shminfo_sz;
833extern unsigned struct_shm_info_sz;
834extern int shmctl_ipc_stat;
835extern int shmctl_ipc_info;
836extern int shmctl_shm_info;
837extern int shmctl_shm_stat;
838#endif
839
840#if !SANITIZER_MAC && !SANITIZER_FREEBSD
841extern unsigned struct_utmp_sz;
842#endif
843#if !SANITIZER_ANDROID
844extern unsigned struct_utmpx_sz;
845#endif
846
847extern int map_fixed;
848
849// ioctl arguments
850struct __sanitizer_ifconf {
851 int ifc_len;
852 union {
853 void *ifcu_req;
854 } ifc_ifcu;
855#if SANITIZER_MAC
856} __attribute__((packed));
857#else
858};
859#endif
860
861#if SANITIZER_LINUX && !SANITIZER_ANDROID
862struct __sanitizer__obstack_chunk {
863 char *limit;
864 struct __sanitizer__obstack_chunk *prev;
865};
866
867struct __sanitizer_obstack {
868 long chunk_size;
869 struct __sanitizer__obstack_chunk *chunk;
870 char *object_base;
871 char *next_free;
872 uptr more_fields[7];
873};
874
875typedef uptr (*__sanitizer_cookie_io_read)(void *cookie, char *buf, uptr size);
876typedef uptr (*__sanitizer_cookie_io_write)(void *cookie, const char *buf,
877 uptr size);
878typedef int (*__sanitizer_cookie_io_seek)(void *cookie, u64 *offset,
879 int whence);
880typedef int (*__sanitizer_cookie_io_close)(void *cookie);
881
882struct __sanitizer_cookie_io_functions_t {
883 __sanitizer_cookie_io_read read;
884 __sanitizer_cookie_io_write write;
885 __sanitizer_cookie_io_seek seek;
886 __sanitizer_cookie_io_close close;
887};
888#endif
889
890#define IOC_NRBITS 8
891#define IOC_TYPEBITS 8
892#if defined(__powerpc__) || defined(__powerpc64__) || defined(__mips__) || \
893 defined(__sparc__)
894#define IOC_SIZEBITS 13
895#define IOC_DIRBITS 3
896#define IOC_NONE 1U
897#define IOC_WRITE 4U
898#define IOC_READ 2U
899#else
900#define IOC_SIZEBITS 14
901#define IOC_DIRBITS 2
902#define IOC_NONE 0U
903#define IOC_WRITE 1U
904#define IOC_READ 2U
905#endif
906#define IOC_NRMASK ((1 << IOC_NRBITS) - 1)
907#define IOC_TYPEMASK ((1 << IOC_TYPEBITS) - 1)
908#define IOC_SIZEMASK ((1 << IOC_SIZEBITS) - 1)
909#if defined(IOC_DIRMASK)
910#undef IOC_DIRMASK
911#endif
912#define IOC_DIRMASK ((1 << IOC_DIRBITS) - 1)
913#define IOC_NRSHIFT 0
914#define IOC_TYPESHIFT (IOC_NRSHIFT + IOC_NRBITS)
915#define IOC_SIZESHIFT (IOC_TYPESHIFT + IOC_TYPEBITS)
916#define IOC_DIRSHIFT (IOC_SIZESHIFT + IOC_SIZEBITS)
917#define EVIOC_EV_MAX 0x1f
918#define EVIOC_ABS_MAX 0x3f
919
920#define IOC_DIR(nr) (((nr) >> IOC_DIRSHIFT) & IOC_DIRMASK)
921#define IOC_TYPE(nr) (((nr) >> IOC_TYPESHIFT) & IOC_TYPEMASK)
922#define IOC_NR(nr) (((nr) >> IOC_NRSHIFT) & IOC_NRMASK)
923
924#if defined(__sparc__)
925// In sparc the 14 bits SIZE field overlaps with the
926// least significant bit of DIR, so either IOC_READ or
927// IOC_WRITE shall be 1 in order to get a non-zero SIZE.
928#define IOC_SIZE(nr) \
929 ((((((nr) >> 29) & 0x7) & (4U | 2U)) == 0) ? 0 : (((nr) >> 16) & 0x3fff))
930#else
931#define IOC_SIZE(nr) (((nr) >> IOC_SIZESHIFT) & IOC_SIZEMASK)
932#endif
933
934extern unsigned struct_ifreq_sz;
935extern unsigned struct_termios_sz;
936extern unsigned struct_winsize_sz;
937
938#if SANITIZER_LINUX
939extern unsigned struct_arpreq_sz;
940extern unsigned struct_cdrom_msf_sz;
941extern unsigned struct_cdrom_multisession_sz;
942extern unsigned struct_cdrom_read_audio_sz;
943extern unsigned struct_cdrom_subchnl_sz;
944extern unsigned struct_cdrom_ti_sz;
945extern unsigned struct_cdrom_tocentry_sz;
946extern unsigned struct_cdrom_tochdr_sz;
947extern unsigned struct_cdrom_volctrl_sz;
948extern unsigned struct_ff_effect_sz;
949extern unsigned struct_floppy_drive_params_sz;
950extern unsigned struct_floppy_drive_struct_sz;
951extern unsigned struct_floppy_fdc_state_sz;
952extern unsigned struct_floppy_max_errors_sz;
953extern unsigned struct_floppy_raw_cmd_sz;
954extern unsigned struct_floppy_struct_sz;
955extern unsigned struct_floppy_write_errors_sz;
956extern unsigned struct_format_descr_sz;
957extern unsigned struct_hd_driveid_sz;
958extern unsigned struct_hd_geometry_sz;
959extern unsigned struct_input_absinfo_sz;
960extern unsigned struct_input_id_sz;
961extern unsigned struct_mtpos_sz;
962extern unsigned struct_termio_sz;
963extern unsigned struct_vt_consize_sz;
964extern unsigned struct_vt_sizes_sz;
965extern unsigned struct_vt_stat_sz;
966#endif // SANITIZER_LINUX
967
968#if SANITIZER_LINUX
969extern unsigned struct_copr_buffer_sz;
970extern unsigned struct_copr_debug_buf_sz;
971extern unsigned struct_copr_msg_sz;
972extern unsigned struct_midi_info_sz;
973extern unsigned struct_mtget_sz;
974extern unsigned struct_mtop_sz;
975extern unsigned struct_rtentry_sz;
976extern unsigned struct_sbi_instrument_sz;
977extern unsigned struct_seq_event_rec_sz;
978extern unsigned struct_synth_info_sz;
979extern unsigned struct_vt_mode_sz;
980#endif // SANITIZER_LINUX
981
982#if SANITIZER_LINUX && !SANITIZER_ANDROID
983extern unsigned struct_ax25_parms_struct_sz;
984extern unsigned struct_cyclades_monitor_sz;
985extern unsigned struct_input_keymap_entry_sz;
986extern unsigned struct_ipx_config_data_sz;
987extern unsigned struct_kbdiacrs_sz;
988extern unsigned struct_kbentry_sz;
989extern unsigned struct_kbkeycode_sz;
990extern unsigned struct_kbsentry_sz;
991extern unsigned struct_mtconfiginfo_sz;
992extern unsigned struct_nr_parms_struct_sz;
993extern unsigned struct_scc_modem_sz;
994extern unsigned struct_scc_stat_sz;
995extern unsigned struct_serial_multiport_struct_sz;
996extern unsigned struct_serial_struct_sz;
997extern unsigned struct_sockaddr_ax25_sz;
998extern unsigned struct_unimapdesc_sz;
999extern unsigned struct_unimapinit_sz;
1000#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
1001
1002extern const unsigned long __sanitizer_bufsiz;
1003
1004#if SANITIZER_LINUX && !SANITIZER_ANDROID
1005extern unsigned struct_audio_buf_info_sz;
1006extern unsigned struct_ppp_stats_sz;
1007#endif // (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID
1008
1009#if !SANITIZER_ANDROID && !SANITIZER_MAC
1010extern unsigned struct_sioc_sg_req_sz;
1011extern unsigned struct_sioc_vif_req_sz;
1012#endif
1013
1014// ioctl request identifiers
1015
1016// A special value to mark ioctls that are not present on the target platform,
1017// when it can not be determined without including any system headers.
1018extern const unsigned IOCTL_NOT_PRESENT;
1019
1020extern unsigned IOCTL_FIOASYNC;
1021extern unsigned IOCTL_FIOCLEX;
1022extern unsigned IOCTL_FIOGETOWN;
1023extern unsigned IOCTL_FIONBIO;
1024extern unsigned IOCTL_FIONCLEX;
1025extern unsigned IOCTL_FIOSETOWN;
1026extern unsigned IOCTL_SIOCADDMULTI;
1027extern unsigned IOCTL_SIOCATMARK;
1028extern unsigned IOCTL_SIOCDELMULTI;
1029extern unsigned IOCTL_SIOCGIFADDR;
1030extern unsigned IOCTL_SIOCGIFBRDADDR;
1031extern unsigned IOCTL_SIOCGIFCONF;
1032extern unsigned IOCTL_SIOCGIFDSTADDR;
1033extern unsigned IOCTL_SIOCGIFFLAGS;
1034extern unsigned IOCTL_SIOCGIFMETRIC;
1035extern unsigned IOCTL_SIOCGIFMTU;
1036extern unsigned IOCTL_SIOCGIFNETMASK;
1037extern unsigned IOCTL_SIOCGPGRP;
1038extern unsigned IOCTL_SIOCSIFADDR;
1039extern unsigned IOCTL_SIOCSIFBRDADDR;
1040extern unsigned IOCTL_SIOCSIFDSTADDR;
1041extern unsigned IOCTL_SIOCSIFFLAGS;
1042extern unsigned IOCTL_SIOCSIFMETRIC;
1043extern unsigned IOCTL_SIOCSIFMTU;
1044extern unsigned IOCTL_SIOCSIFNETMASK;
1045extern unsigned IOCTL_SIOCSPGRP;
1046extern unsigned IOCTL_TIOCCONS;
1047extern unsigned IOCTL_TIOCEXCL;
1048extern unsigned IOCTL_TIOCGETD;
1049extern unsigned IOCTL_TIOCGPGRP;
1050extern unsigned IOCTL_TIOCGWINSZ;
1051extern unsigned IOCTL_TIOCMBIC;
1052extern unsigned IOCTL_TIOCMBIS;
1053extern unsigned IOCTL_TIOCMGET;
1054extern unsigned IOCTL_TIOCMSET;
1055extern unsigned IOCTL_TIOCNOTTY;
1056extern unsigned IOCTL_TIOCNXCL;
1057extern unsigned IOCTL_TIOCOUTQ;
1058extern unsigned IOCTL_TIOCPKT;
1059extern unsigned IOCTL_TIOCSCTTY;
1060extern unsigned IOCTL_TIOCSETD;
1061extern unsigned IOCTL_TIOCSPGRP;
1062extern unsigned IOCTL_TIOCSTI;
1063extern unsigned IOCTL_TIOCSWINSZ;
1064#if SANITIZER_LINUX && !SANITIZER_ANDROID
1065extern unsigned IOCTL_SIOCGETSGCNT;
1066extern unsigned IOCTL_SIOCGETVIFCNT;
1067#endif
1068#if SANITIZER_LINUX
1069extern unsigned IOCTL_EVIOCGABS;
1070extern unsigned IOCTL_EVIOCGBIT;
1071extern unsigned IOCTL_EVIOCGEFFECTS;
1072extern unsigned IOCTL_EVIOCGID;
1073extern unsigned IOCTL_EVIOCGKEY;
1074extern unsigned IOCTL_EVIOCGKEYCODE;
1075extern unsigned IOCTL_EVIOCGLED;
1076extern unsigned IOCTL_EVIOCGNAME;
1077extern unsigned IOCTL_EVIOCGPHYS;
1078extern unsigned IOCTL_EVIOCGRAB;
1079extern unsigned IOCTL_EVIOCGREP;
1080extern unsigned IOCTL_EVIOCGSND;
1081extern unsigned IOCTL_EVIOCGSW;
1082extern unsigned IOCTL_EVIOCGUNIQ;
1083extern unsigned IOCTL_EVIOCGVERSION;
1084extern unsigned IOCTL_EVIOCRMFF;
1085extern unsigned IOCTL_EVIOCSABS;
1086extern unsigned IOCTL_EVIOCSFF;
1087extern unsigned IOCTL_EVIOCSKEYCODE;
1088extern unsigned IOCTL_EVIOCSREP;
1089extern unsigned IOCTL_BLKFLSBUF;
1090extern unsigned IOCTL_BLKGETSIZE;
1091extern unsigned IOCTL_BLKRAGET;
1092extern unsigned IOCTL_BLKRASET;
1093extern unsigned IOCTL_BLKROGET;
1094extern unsigned IOCTL_BLKROSET;
1095extern unsigned IOCTL_BLKRRPART;
1096extern unsigned IOCTL_CDROMAUDIOBUFSIZ;
1097extern unsigned IOCTL_CDROMEJECT;
1098extern unsigned IOCTL_CDROMEJECT_SW;
1099extern unsigned IOCTL_CDROMMULTISESSION;
1100extern unsigned IOCTL_CDROMPAUSE;
1101extern unsigned IOCTL_CDROMPLAYMSF;
1102extern unsigned IOCTL_CDROMPLAYTRKIND;
1103extern unsigned IOCTL_CDROMREADAUDIO;
1104extern unsigned IOCTL_CDROMREADCOOKED;
1105extern unsigned IOCTL_CDROMREADMODE1;
1106extern unsigned IOCTL_CDROMREADMODE2;
1107extern unsigned IOCTL_CDROMREADRAW;
1108extern unsigned IOCTL_CDROMREADTOCENTRY;
1109extern unsigned IOCTL_CDROMREADTOCHDR;
1110extern unsigned IOCTL_CDROMRESET;
1111extern unsigned IOCTL_CDROMRESUME;
1112extern unsigned IOCTL_CDROMSEEK;
1113extern unsigned IOCTL_CDROMSTART;
1114extern unsigned IOCTL_CDROMSTOP;
1115extern unsigned IOCTL_CDROMSUBCHNL;
1116extern unsigned IOCTL_CDROMVOLCTRL;
1117extern unsigned IOCTL_CDROMVOLREAD;
1118extern unsigned IOCTL_CDROM_GET_UPC;
1119extern unsigned IOCTL_FDCLRPRM;
1120extern unsigned IOCTL_FDDEFPRM;
1121extern unsigned IOCTL_FDFLUSH;
1122extern unsigned IOCTL_FDFMTBEG;
1123extern unsigned IOCTL_FDFMTEND;
1124extern unsigned IOCTL_FDFMTTRK;
1125extern unsigned IOCTL_FDGETDRVPRM;
1126extern unsigned IOCTL_FDGETDRVSTAT;
1127extern unsigned IOCTL_FDGETDRVTYP;
1128extern unsigned IOCTL_FDGETFDCSTAT;
1129extern unsigned IOCTL_FDGETMAXERRS;
1130extern unsigned IOCTL_FDGETPRM;
1131extern unsigned IOCTL_FDMSGOFF;
1132extern unsigned IOCTL_FDMSGON;
1133extern unsigned IOCTL_FDPOLLDRVSTAT;
1134extern unsigned IOCTL_FDRAWCMD;
1135extern unsigned IOCTL_FDRESET;
1136extern unsigned IOCTL_FDSETDRVPRM;
1137extern unsigned IOCTL_FDSETEMSGTRESH;
1138extern unsigned IOCTL_FDSETMAXERRS;
1139extern unsigned IOCTL_FDSETPRM;
1140extern unsigned IOCTL_FDTWADDLE;
1141extern unsigned IOCTL_FDWERRORCLR;
1142extern unsigned IOCTL_FDWERRORGET;
1143extern unsigned IOCTL_HDIO_DRIVE_CMD;
1144extern unsigned IOCTL_HDIO_GETGEO;
1145extern unsigned IOCTL_HDIO_GET_32BIT;
1146extern unsigned IOCTL_HDIO_GET_DMA;
1147extern unsigned IOCTL_HDIO_GET_IDENTITY;
1148extern unsigned IOCTL_HDIO_GET_KEEPSETTINGS;
1149extern unsigned IOCTL_HDIO_GET_MULTCOUNT;
1150extern unsigned IOCTL_HDIO_GET_NOWERR;
1151extern unsigned IOCTL_HDIO_GET_UNMASKINTR;
1152extern unsigned IOCTL_HDIO_SET_32BIT;
1153extern unsigned IOCTL_HDIO_SET_DMA;
1154extern unsigned IOCTL_HDIO_SET_KEEPSETTINGS;
1155extern unsigned IOCTL_HDIO_SET_MULTCOUNT;
1156extern unsigned IOCTL_HDIO_SET_NOWERR;
1157extern unsigned IOCTL_HDIO_SET_UNMASKINTR;
1158extern unsigned IOCTL_MTIOCPOS;
1159extern unsigned IOCTL_PPPIOCGASYNCMAP;
1160extern unsigned IOCTL_PPPIOCGDEBUG;
1161extern unsigned IOCTL_PPPIOCGFLAGS;
1162extern unsigned IOCTL_PPPIOCGUNIT;
1163extern unsigned IOCTL_PPPIOCGXASYNCMAP;
1164extern unsigned IOCTL_PPPIOCSASYNCMAP;
1165extern unsigned IOCTL_PPPIOCSDEBUG;
1166extern unsigned IOCTL_PPPIOCSFLAGS;
1167extern unsigned IOCTL_PPPIOCSMAXCID;
1168extern unsigned IOCTL_PPPIOCSMRU;
1169extern unsigned IOCTL_PPPIOCSXASYNCMAP;
1170extern unsigned IOCTL_SIOCDARP;
1171extern unsigned IOCTL_SIOCDRARP;
1172extern unsigned IOCTL_SIOCGARP;
1173extern unsigned IOCTL_SIOCGIFENCAP;
1174extern unsigned IOCTL_SIOCGIFHWADDR;
1175extern unsigned IOCTL_SIOCGIFMAP;
1176extern unsigned IOCTL_SIOCGIFMEM;
1177extern unsigned IOCTL_SIOCGIFNAME;
1178extern unsigned IOCTL_SIOCGIFSLAVE;
1179extern unsigned IOCTL_SIOCGRARP;
1180extern unsigned IOCTL_SIOCGSTAMP;
1181extern unsigned IOCTL_SIOCSARP;
1182extern unsigned IOCTL_SIOCSIFENCAP;
1183extern unsigned IOCTL_SIOCSIFHWADDR;
1184extern unsigned IOCTL_SIOCSIFLINK;
1185extern unsigned IOCTL_SIOCSIFMAP;
1186extern unsigned IOCTL_SIOCSIFMEM;
1187extern unsigned IOCTL_SIOCSIFSLAVE;
1188extern unsigned IOCTL_SIOCSRARP;
1189extern unsigned IOCTL_SNDCTL_COPR_HALT;
1190extern unsigned IOCTL_SNDCTL_COPR_LOAD;
1191extern unsigned IOCTL_SNDCTL_COPR_RCODE;
1192extern unsigned IOCTL_SNDCTL_COPR_RCVMSG;
1193extern unsigned IOCTL_SNDCTL_COPR_RDATA;
1194extern unsigned IOCTL_SNDCTL_COPR_RESET;
1195extern unsigned IOCTL_SNDCTL_COPR_RUN;
1196extern unsigned IOCTL_SNDCTL_COPR_SENDMSG;
1197extern unsigned IOCTL_SNDCTL_COPR_WCODE;
1198extern unsigned IOCTL_SNDCTL_COPR_WDATA;
1199extern unsigned IOCTL_TCFLSH;
1200extern unsigned IOCTL_TCGETA;
1201extern unsigned IOCTL_TCGETS;
1202extern unsigned IOCTL_TCSBRK;
1203extern unsigned IOCTL_TCSBRKP;
1204extern unsigned IOCTL_TCSETA;
1205extern unsigned IOCTL_TCSETAF;
1206extern unsigned IOCTL_TCSETAW;
1207extern unsigned IOCTL_TCSETS;
1208extern unsigned IOCTL_TCSETSF;
1209extern unsigned IOCTL_TCSETSW;
1210extern unsigned IOCTL_TCXONC;
1211extern unsigned IOCTL_TIOCGLCKTRMIOS;
1212extern unsigned IOCTL_TIOCGSOFTCAR;
1213extern unsigned IOCTL_TIOCINQ;
1214extern unsigned IOCTL_TIOCLINUX;
1215extern unsigned IOCTL_TIOCSERCONFIG;
1216extern unsigned IOCTL_TIOCSERGETLSR;
1217extern unsigned IOCTL_TIOCSERGWILD;
1218extern unsigned IOCTL_TIOCSERSWILD;
1219extern unsigned IOCTL_TIOCSLCKTRMIOS;
1220extern unsigned IOCTL_TIOCSSOFTCAR;
1221extern unsigned IOCTL_VT_DISALLOCATE;
1222extern unsigned IOCTL_VT_GETSTATE;
1223extern unsigned IOCTL_VT_RESIZE;
1224extern unsigned IOCTL_VT_RESIZEX;
1225extern unsigned IOCTL_VT_SENDSIG;
1226extern unsigned IOCTL_MTIOCGET;
1227extern unsigned IOCTL_MTIOCTOP;
1228extern unsigned IOCTL_SIOCADDRT;
1229extern unsigned IOCTL_SIOCDELRT;
1230extern unsigned IOCTL_SNDCTL_DSP_GETBLKSIZE;
1231extern unsigned IOCTL_SNDCTL_DSP_GETFMTS;
1232extern unsigned IOCTL_SNDCTL_DSP_NONBLOCK;
1233extern unsigned IOCTL_SNDCTL_DSP_POST;
1234extern unsigned IOCTL_SNDCTL_DSP_RESET;
1235extern unsigned IOCTL_SNDCTL_DSP_SETFMT;
1236extern unsigned IOCTL_SNDCTL_DSP_SETFRAGMENT;
1237extern unsigned IOCTL_SNDCTL_DSP_SPEED;
1238extern unsigned IOCTL_SNDCTL_DSP_STEREO;
1239extern unsigned IOCTL_SNDCTL_DSP_SUBDIVIDE;
1240extern unsigned IOCTL_SNDCTL_DSP_SYNC;
1241extern unsigned IOCTL_SNDCTL_FM_4OP_ENABLE;
1242extern unsigned IOCTL_SNDCTL_FM_LOAD_INSTR;
1243extern unsigned IOCTL_SNDCTL_MIDI_INFO;
1244extern unsigned IOCTL_SNDCTL_MIDI_PRETIME;
1245extern unsigned IOCTL_SNDCTL_SEQ_CTRLRATE;
1246extern unsigned IOCTL_SNDCTL_SEQ_GETINCOUNT;
1247extern unsigned IOCTL_SNDCTL_SEQ_GETOUTCOUNT;
1248extern unsigned IOCTL_SNDCTL_SEQ_NRMIDIS;
1249extern unsigned IOCTL_SNDCTL_SEQ_NRSYNTHS;
1250extern unsigned IOCTL_SNDCTL_SEQ_OUTOFBAND;
1251extern unsigned IOCTL_SNDCTL_SEQ_PANIC;
1252extern unsigned IOCTL_SNDCTL_SEQ_PERCMODE;
1253extern unsigned IOCTL_SNDCTL_SEQ_RESET;
1254extern unsigned IOCTL_SNDCTL_SEQ_RESETSAMPLES;
1255extern unsigned IOCTL_SNDCTL_SEQ_SYNC;
1256extern unsigned IOCTL_SNDCTL_SEQ_TESTMIDI;
1257extern unsigned IOCTL_SNDCTL_SEQ_THRESHOLD;
1258extern unsigned IOCTL_SNDCTL_SYNTH_INFO;
1259extern unsigned IOCTL_SNDCTL_SYNTH_MEMAVL;
1260extern unsigned IOCTL_SNDCTL_TMR_CONTINUE;
1261extern unsigned IOCTL_SNDCTL_TMR_METRONOME;
1262extern unsigned IOCTL_SNDCTL_TMR_SELECT;
1263extern unsigned IOCTL_SNDCTL_TMR_SOURCE;
1264extern unsigned IOCTL_SNDCTL_TMR_START;
1265extern unsigned IOCTL_SNDCTL_TMR_STOP;
1266extern unsigned IOCTL_SNDCTL_TMR_TEMPO;
1267extern unsigned IOCTL_SNDCTL_TMR_TIMEBASE;
1268extern unsigned IOCTL_SOUND_MIXER_READ_ALTPCM;
1269extern unsigned IOCTL_SOUND_MIXER_READ_BASS;
1270extern unsigned IOCTL_SOUND_MIXER_READ_CAPS;
1271extern unsigned IOCTL_SOUND_MIXER_READ_CD;
1272extern unsigned IOCTL_SOUND_MIXER_READ_DEVMASK;
1273extern unsigned IOCTL_SOUND_MIXER_READ_ENHANCE;
1274extern unsigned IOCTL_SOUND_MIXER_READ_IGAIN;
1275extern unsigned IOCTL_SOUND_MIXER_READ_IMIX;
1276extern unsigned IOCTL_SOUND_MIXER_READ_LINE1;
1277extern unsigned IOCTL_SOUND_MIXER_READ_LINE2;
1278extern unsigned IOCTL_SOUND_MIXER_READ_LINE3;
1279extern unsigned IOCTL_SOUND_MIXER_READ_LINE;
1280extern unsigned IOCTL_SOUND_MIXER_READ_LOUD;
1281extern unsigned IOCTL_SOUND_MIXER_READ_MIC;
1282extern unsigned IOCTL_SOUND_MIXER_READ_MUTE;
1283extern unsigned IOCTL_SOUND_MIXER_READ_OGAIN;
1284extern unsigned IOCTL_SOUND_MIXER_READ_PCM;
1285extern unsigned IOCTL_SOUND_MIXER_READ_RECLEV;
1286extern unsigned IOCTL_SOUND_MIXER_READ_RECMASK;
1287extern unsigned IOCTL_SOUND_MIXER_READ_RECSRC;
1288extern unsigned IOCTL_SOUND_MIXER_READ_SPEAKER;
1289extern unsigned IOCTL_SOUND_MIXER_READ_STEREODEVS;
1290extern unsigned IOCTL_SOUND_MIXER_READ_SYNTH;
1291extern unsigned IOCTL_SOUND_MIXER_READ_TREBLE;
1292extern unsigned IOCTL_SOUND_MIXER_READ_VOLUME;
1293extern unsigned IOCTL_SOUND_MIXER_WRITE_ALTPCM;
1294extern unsigned IOCTL_SOUND_MIXER_WRITE_BASS;
1295extern unsigned IOCTL_SOUND_MIXER_WRITE_CD;
1296extern unsigned IOCTL_SOUND_MIXER_WRITE_ENHANCE;
1297extern unsigned IOCTL_SOUND_MIXER_WRITE_IGAIN;
1298extern unsigned IOCTL_SOUND_MIXER_WRITE_IMIX;
1299extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE1;
1300extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE2;
1301extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE3;
1302extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE;
1303extern unsigned IOCTL_SOUND_MIXER_WRITE_LOUD;
1304extern unsigned IOCTL_SOUND_MIXER_WRITE_MIC;
1305extern unsigned IOCTL_SOUND_MIXER_WRITE_MUTE;
1306extern unsigned IOCTL_SOUND_MIXER_WRITE_OGAIN;
1307extern unsigned IOCTL_SOUND_MIXER_WRITE_PCM;
1308extern unsigned IOCTL_SOUND_MIXER_WRITE_RECLEV;
1309extern unsigned IOCTL_SOUND_MIXER_WRITE_RECSRC;
1310extern unsigned IOCTL_SOUND_MIXER_WRITE_SPEAKER;
1311extern unsigned IOCTL_SOUND_MIXER_WRITE_SYNTH;
1312extern unsigned IOCTL_SOUND_MIXER_WRITE_TREBLE;
1313extern unsigned IOCTL_SOUND_MIXER_WRITE_VOLUME;
1314extern unsigned IOCTL_SOUND_PCM_READ_BITS;
1315extern unsigned IOCTL_SOUND_PCM_READ_CHANNELS;
1316extern unsigned IOCTL_SOUND_PCM_READ_FILTER;
1317extern unsigned IOCTL_SOUND_PCM_READ_RATE;
1318extern unsigned IOCTL_SOUND_PCM_WRITE_CHANNELS;
1319extern unsigned IOCTL_SOUND_PCM_WRITE_FILTER;
1320extern unsigned IOCTL_VT_ACTIVATE;
1321extern unsigned IOCTL_VT_GETMODE;
1322extern unsigned IOCTL_VT_OPENQRY;
1323extern unsigned IOCTL_VT_RELDISP;
1324extern unsigned IOCTL_VT_SETMODE;
1325extern unsigned IOCTL_VT_WAITACTIVE;
1326#endif // SANITIZER_LINUX
1327
1328#if SANITIZER_LINUX && !SANITIZER_ANDROID
1329extern unsigned IOCTL_CYGETDEFTHRESH;
1330extern unsigned IOCTL_CYGETDEFTIMEOUT;
1331extern unsigned IOCTL_CYGETMON;
1332extern unsigned IOCTL_CYGETTHRESH;
1333extern unsigned IOCTL_CYGETTIMEOUT;
1334extern unsigned IOCTL_CYSETDEFTHRESH;
1335extern unsigned IOCTL_CYSETDEFTIMEOUT;
1336extern unsigned IOCTL_CYSETTHRESH;
1337extern unsigned IOCTL_CYSETTIMEOUT;
1338extern unsigned IOCTL_EQL_EMANCIPATE;
1339extern unsigned IOCTL_EQL_ENSLAVE;
1340extern unsigned IOCTL_EQL_GETMASTRCFG;
1341extern unsigned IOCTL_EQL_GETSLAVECFG;
1342extern unsigned IOCTL_EQL_SETMASTRCFG;
1343extern unsigned IOCTL_EQL_SETSLAVECFG;
1344extern unsigned IOCTL_EVIOCGKEYCODE_V2;
1345extern unsigned IOCTL_EVIOCGPROP;
1346extern unsigned IOCTL_EVIOCSKEYCODE_V2;
1347extern unsigned IOCTL_FS_IOC_GETFLAGS;
1348extern unsigned IOCTL_FS_IOC_GETVERSION;
1349extern unsigned IOCTL_FS_IOC_SETFLAGS;
1350extern unsigned IOCTL_FS_IOC_SETVERSION;
1351extern unsigned IOCTL_GIO_CMAP;
1352extern unsigned IOCTL_GIO_FONT;
1353extern unsigned IOCTL_GIO_UNIMAP;
1354extern unsigned IOCTL_GIO_UNISCRNMAP;
1355extern unsigned IOCTL_KDADDIO;
1356extern unsigned IOCTL_KDDELIO;
1357extern unsigned IOCTL_KDGETKEYCODE;
1358extern unsigned IOCTL_KDGKBDIACR;
1359extern unsigned IOCTL_KDGKBENT;
1360extern unsigned IOCTL_KDGKBLED;
1361extern unsigned IOCTL_KDGKBMETA;
1362extern unsigned IOCTL_KDGKBSENT;
1363extern unsigned IOCTL_KDMAPDISP;
1364extern unsigned IOCTL_KDSETKEYCODE;
1365extern unsigned IOCTL_KDSIGACCEPT;
1366extern unsigned IOCTL_KDSKBDIACR;
1367extern unsigned IOCTL_KDSKBENT;
1368extern unsigned IOCTL_KDSKBLED;
1369extern unsigned IOCTL_KDSKBMETA;
1370extern unsigned IOCTL_KDSKBSENT;
1371extern unsigned IOCTL_KDUNMAPDISP;
1372extern unsigned IOCTL_LPABORT;
1373extern unsigned IOCTL_LPABORTOPEN;
1374extern unsigned IOCTL_LPCAREFUL;
1375extern unsigned IOCTL_LPCHAR;
1376extern unsigned IOCTL_LPGETIRQ;
1377extern unsigned IOCTL_LPGETSTATUS;
1378extern unsigned IOCTL_LPRESET;
1379extern unsigned IOCTL_LPSETIRQ;
1380extern unsigned IOCTL_LPTIME;
1381extern unsigned IOCTL_LPWAIT;
1382extern unsigned IOCTL_MTIOCGETCONFIG;
1383extern unsigned IOCTL_MTIOCSETCONFIG;
1384extern unsigned IOCTL_PIO_CMAP;
1385extern unsigned IOCTL_PIO_FONT;
1386extern unsigned IOCTL_PIO_UNIMAP;
1387extern unsigned IOCTL_PIO_UNIMAPCLR;
1388extern unsigned IOCTL_PIO_UNISCRNMAP;
1389extern unsigned IOCTL_SCSI_IOCTL_GET_IDLUN;
1390extern unsigned IOCTL_SCSI_IOCTL_PROBE_HOST;
1391extern unsigned IOCTL_SCSI_IOCTL_TAGGED_DISABLE;
1392extern unsigned IOCTL_SCSI_IOCTL_TAGGED_ENABLE;
1393extern unsigned IOCTL_SIOCAIPXITFCRT;
1394extern unsigned IOCTL_SIOCAIPXPRISLT;
1395extern unsigned IOCTL_SIOCAX25ADDUID;
1396extern unsigned IOCTL_SIOCAX25DELUID;
1397extern unsigned IOCTL_SIOCAX25GETPARMS;
1398extern unsigned IOCTL_SIOCAX25GETUID;
1399extern unsigned IOCTL_SIOCAX25NOUID;
1400extern unsigned IOCTL_SIOCAX25SETPARMS;
1401extern unsigned IOCTL_SIOCDEVPLIP;
1402extern unsigned IOCTL_SIOCIPXCFGDATA;
1403extern unsigned IOCTL_SIOCNRDECOBS;
1404extern unsigned IOCTL_SIOCNRGETPARMS;
1405extern unsigned IOCTL_SIOCNRRTCTL;
1406extern unsigned IOCTL_SIOCNRSETPARMS;
1407extern unsigned IOCTL_SNDCTL_DSP_GETISPACE;
1408extern unsigned IOCTL_SNDCTL_DSP_GETOSPACE;
1409extern unsigned IOCTL_TIOCGSERIAL;
1410extern unsigned IOCTL_TIOCSERGETMULTI;
1411extern unsigned IOCTL_TIOCSERSETMULTI;
1412extern unsigned IOCTL_TIOCSSERIAL;
1413extern unsigned IOCTL_GIO_SCRNMAP;
1414extern unsigned IOCTL_KDDISABIO;
1415extern unsigned IOCTL_KDENABIO;
1416extern unsigned IOCTL_KDGETLED;
1417extern unsigned IOCTL_KDGETMODE;
1418extern unsigned IOCTL_KDGKBMODE;
1419extern unsigned IOCTL_KDGKBTYPE;
1420extern unsigned IOCTL_KDMKTONE;
1421extern unsigned IOCTL_KDSETLED;
1422extern unsigned IOCTL_KDSETMODE;
1423extern unsigned IOCTL_KDSKBMODE;
1424extern unsigned IOCTL_KIOCSOUND;
1425extern unsigned IOCTL_PIO_SCRNMAP;
1426#endif
1427
1428extern const int si_SEGV_MAPERR;
1429extern const int si_SEGV_ACCERR;
1430} // namespace __sanitizer
1431
1432#define CHECK_TYPE_SIZE(TYPE) \
1433 COMPILER_CHECK(sizeof(__sanitizer_##TYPE) == sizeof(TYPE))
1434
1435#define CHECK_SIZE_AND_OFFSET(CLASS, MEMBER) \
1436 COMPILER_CHECK(sizeof(((__sanitizer_##CLASS *)NULL)->MEMBER) == \
1437 sizeof(((CLASS *)NULL)->MEMBER)); \
1438 COMPILER_CHECK(offsetof(__sanitizer_##CLASS, MEMBER) == \
1439 offsetof(CLASS, MEMBER))
1440
1441// For sigaction, which is a function and struct at the same time,
1442// and thus requires explicit "struct" in sizeof() expression.
1443#define CHECK_STRUCT_SIZE_AND_OFFSET(CLASS, MEMBER) \
1444 COMPILER_CHECK(sizeof(((struct __sanitizer_##CLASS *)NULL)->MEMBER) == \
1445 sizeof(((struct CLASS *)NULL)->MEMBER)); \
1446 COMPILER_CHECK(offsetof(struct __sanitizer_##CLASS, MEMBER) == \
1447 offsetof(struct CLASS, MEMBER))
1448
1449#define SIGACTION_SYMNAME sigaction
1450
1451#endif // SANITIZER_LINUX || SANITIZER_MAC
1452
1453#endif
lib/tsan/sanitizer_common/sanitizer_platform_limits_solaris.cpp created+366
...@@ -0,0 +1,366 @@
1//===-- sanitizer_platform_limits_solaris.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 Sanitizer common code.
10//
11// Sizes and layouts of platform-specific Solaris data structures.
12//===----------------------------------------------------------------------===//
13
14#include "sanitizer_platform.h"
15
16#if SANITIZER_SOLARIS
17#include <arpa/inet.h>
18#include <dirent.h>
19#include <glob.h>
20#include <grp.h>
21#include <ifaddrs.h>
22#include <limits.h>
23#include <link.h>
24#include <net/if.h>
25#include <net/route.h>
26#include <netdb.h>
27#include <netinet/ip_mroute.h>
28#include <poll.h>
29#include <pthread.h>
30#include <pwd.h>
31#include <rpc/xdr.h>
32#include <semaphore.h>
33#include <signal.h>
34#include <stddef.h>
35#include <sys/ethernet.h>
36#include <sys/filio.h>
37#include <sys/ipc.h>
38#include <sys/mman.h>
39#include <sys/mount.h>
40#include <sys/mtio.h>
41#include <sys/ptyvar.h>
42#include <sys/resource.h>
43#include <sys/shm.h>
44#include <sys/socket.h>
45#include <sys/sockio.h>
46#include <sys/stat.h>
47#include <sys/statfs.h>
48#include <sys/statvfs.h>
49#include <sys/time.h>
50#include <sys/timeb.h>
51#include <sys/times.h>
52#include <sys/types.h>
53#include <sys/utsname.h>
54#include <termios.h>
55#include <time.h>
56#include <utmp.h>
57#include <utmpx.h>
58#include <wchar.h>
59#include <wordexp.h>
60
61// Include these after system headers to avoid name clashes and ambiguities.
62#include "sanitizer_internal_defs.h"
63#include "sanitizer_platform_limits_solaris.h"
64
65namespace __sanitizer {
66 unsigned struct_utsname_sz = sizeof(struct utsname);
67 unsigned struct_stat_sz = sizeof(struct stat);
68 unsigned struct_stat64_sz = sizeof(struct stat64);
69 unsigned struct_rusage_sz = sizeof(struct rusage);
70 unsigned struct_tm_sz = sizeof(struct tm);
71 unsigned struct_passwd_sz = sizeof(struct passwd);
72 unsigned struct_group_sz = sizeof(struct group);
73 unsigned siginfo_t_sz = sizeof(siginfo_t);
74 unsigned struct_sigaction_sz = sizeof(struct sigaction);
75 unsigned struct_stack_t_sz = sizeof(stack_t);
76 unsigned struct_itimerval_sz = sizeof(struct itimerval);
77 unsigned pthread_t_sz = sizeof(pthread_t);
78 unsigned pthread_mutex_t_sz = sizeof(pthread_mutex_t);
79 unsigned pthread_cond_t_sz = sizeof(pthread_cond_t);
80 unsigned pid_t_sz = sizeof(pid_t);
81 unsigned timeval_sz = sizeof(timeval);
82 unsigned uid_t_sz = sizeof(uid_t);
83 unsigned gid_t_sz = sizeof(gid_t);
84 unsigned mbstate_t_sz = sizeof(mbstate_t);
85 unsigned sigset_t_sz = sizeof(sigset_t);
86 unsigned struct_timezone_sz = sizeof(struct timezone);
87 unsigned struct_tms_sz = sizeof(struct tms);
88 unsigned struct_sigevent_sz = sizeof(struct sigevent);
89 unsigned struct_sched_param_sz = sizeof(struct sched_param);
90 unsigned struct_statfs_sz = sizeof(struct statfs);
91 unsigned struct_sockaddr_sz = sizeof(struct sockaddr);
92 unsigned ucontext_t_sz = sizeof(ucontext_t);
93 unsigned struct_timespec_sz = sizeof(struct timespec);
94#if SANITIZER_SOLARIS32
95 unsigned struct_statvfs64_sz = sizeof(struct statvfs64);
96#endif
97 unsigned struct_statvfs_sz = sizeof(struct statvfs);
98
99 const uptr sig_ign = (uptr)SIG_IGN;
100 const uptr sig_dfl = (uptr)SIG_DFL;
101 const uptr sig_err = (uptr)SIG_ERR;
102 const uptr sa_siginfo = (uptr)SA_SIGINFO;
103
104 int shmctl_ipc_stat = (int)IPC_STAT;
105
106 unsigned struct_utmp_sz = sizeof(struct utmp);
107 unsigned struct_utmpx_sz = sizeof(struct utmpx);
108
109 int map_fixed = MAP_FIXED;
110
111 int af_inet = (int)AF_INET;
112 int af_inet6 = (int)AF_INET6;
113
114 uptr __sanitizer_in_addr_sz(int af) {
115 if (af == AF_INET)
116 return sizeof(struct in_addr);
117 else if (af == AF_INET6)
118 return sizeof(struct in6_addr);
119 else
120 return 0;
121 }
122
123 unsigned struct_ElfW_Phdr_sz = sizeof(ElfW(Phdr));
124
125 int glob_nomatch = GLOB_NOMATCH;
126
127 unsigned path_max = PATH_MAX;
128
129 // ioctl arguments
130 unsigned struct_ifreq_sz = sizeof(struct ifreq);
131 unsigned struct_termios_sz = sizeof(struct termios);
132 unsigned struct_winsize_sz = sizeof(struct winsize);
133
134 unsigned struct_sioc_sg_req_sz = sizeof(struct sioc_sg_req);
135 unsigned struct_sioc_vif_req_sz = sizeof(struct sioc_vif_req);
136
137 const unsigned IOCTL_NOT_PRESENT = 0;
138
139 unsigned IOCTL_FIOASYNC = FIOASYNC;
140 unsigned IOCTL_FIOCLEX = FIOCLEX;
141 unsigned IOCTL_FIOGETOWN = FIOGETOWN;
142 unsigned IOCTL_FIONBIO = FIONBIO;
143 unsigned IOCTL_FIONCLEX = FIONCLEX;
144 unsigned IOCTL_FIOSETOWN = FIOSETOWN;
145 unsigned IOCTL_SIOCADDMULTI = SIOCADDMULTI;
146 unsigned IOCTL_SIOCATMARK = SIOCATMARK;
147 unsigned IOCTL_SIOCDELMULTI = SIOCDELMULTI;
148 unsigned IOCTL_SIOCGIFADDR = SIOCGIFADDR;
149 unsigned IOCTL_SIOCGIFBRDADDR = SIOCGIFBRDADDR;
150 unsigned IOCTL_SIOCGIFCONF = SIOCGIFCONF;
151 unsigned IOCTL_SIOCGIFDSTADDR = SIOCGIFDSTADDR;
152 unsigned IOCTL_SIOCGIFFLAGS = SIOCGIFFLAGS;
153 unsigned IOCTL_SIOCGIFMETRIC = SIOCGIFMETRIC;
154 unsigned IOCTL_SIOCGIFMTU = SIOCGIFMTU;
155 unsigned IOCTL_SIOCGIFNETMASK = SIOCGIFNETMASK;
156 unsigned IOCTL_SIOCGPGRP = SIOCGPGRP;
157 unsigned IOCTL_SIOCSIFADDR = SIOCSIFADDR;
158 unsigned IOCTL_SIOCSIFBRDADDR = SIOCSIFBRDADDR;
159 unsigned IOCTL_SIOCSIFDSTADDR = SIOCSIFDSTADDR;
160 unsigned IOCTL_SIOCSIFFLAGS = SIOCSIFFLAGS;
161 unsigned IOCTL_SIOCSIFMETRIC = SIOCSIFMETRIC;
162 unsigned IOCTL_SIOCSIFMTU = SIOCSIFMTU;
163 unsigned IOCTL_SIOCSIFNETMASK = SIOCSIFNETMASK;
164 unsigned IOCTL_SIOCSPGRP = SIOCSPGRP;
165 unsigned IOCTL_TIOCEXCL = TIOCEXCL;
166 unsigned IOCTL_TIOCGETD = TIOCGETD;
167 unsigned IOCTL_TIOCGPGRP = TIOCGPGRP;
168 unsigned IOCTL_TIOCGWINSZ = TIOCGWINSZ;
169 unsigned IOCTL_TIOCMBIC = TIOCMBIC;
170 unsigned IOCTL_TIOCMBIS = TIOCMBIS;
171 unsigned IOCTL_TIOCMGET = TIOCMGET;
172 unsigned IOCTL_TIOCMSET = TIOCMSET;
173 unsigned IOCTL_TIOCNOTTY = TIOCNOTTY;
174 unsigned IOCTL_TIOCNXCL = TIOCNXCL;
175 unsigned IOCTL_TIOCOUTQ = TIOCOUTQ;
176 unsigned IOCTL_TIOCPKT = TIOCPKT;
177 unsigned IOCTL_TIOCSCTTY = TIOCSCTTY;
178 unsigned IOCTL_TIOCSETD = TIOCSETD;
179 unsigned IOCTL_TIOCSPGRP = TIOCSPGRP;
180 unsigned IOCTL_TIOCSTI = TIOCSTI;
181 unsigned IOCTL_TIOCSWINSZ = TIOCSWINSZ;
182
183 unsigned IOCTL_MTIOCGET = MTIOCGET;
184 unsigned IOCTL_MTIOCTOP = MTIOCTOP;
185
186 const int si_SEGV_MAPERR = SEGV_MAPERR;
187 const int si_SEGV_ACCERR = SEGV_ACCERR;
188} // namespace __sanitizer
189
190using namespace __sanitizer;
191
192COMPILER_CHECK(sizeof(__sanitizer_pthread_attr_t) >= sizeof(pthread_attr_t));
193
194COMPILER_CHECK(sizeof(socklen_t) == sizeof(unsigned));
195CHECK_TYPE_SIZE(pthread_key_t);
196
197// There are more undocumented fields in dl_phdr_info that we are not interested
198// in.
199COMPILER_CHECK(sizeof(__sanitizer_dl_phdr_info) <= sizeof(dl_phdr_info));
200CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_addr);
201CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_name);
202CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_phdr);
203CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_phnum);
204
205CHECK_TYPE_SIZE(glob_t);
206CHECK_SIZE_AND_OFFSET(glob_t, gl_pathc);
207CHECK_SIZE_AND_OFFSET(glob_t, gl_pathv);
208CHECK_SIZE_AND_OFFSET(glob_t, gl_offs);
209
210CHECK_TYPE_SIZE(addrinfo);
211CHECK_SIZE_AND_OFFSET(addrinfo, ai_flags);
212CHECK_SIZE_AND_OFFSET(addrinfo, ai_family);
213CHECK_SIZE_AND_OFFSET(addrinfo, ai_socktype);
214CHECK_SIZE_AND_OFFSET(addrinfo, ai_protocol);
215CHECK_SIZE_AND_OFFSET(addrinfo, ai_protocol);
216CHECK_SIZE_AND_OFFSET(addrinfo, ai_addrlen);
217CHECK_SIZE_AND_OFFSET(addrinfo, ai_canonname);
218CHECK_SIZE_AND_OFFSET(addrinfo, ai_addr);
219
220CHECK_TYPE_SIZE(hostent);
221CHECK_SIZE_AND_OFFSET(hostent, h_name);
222CHECK_SIZE_AND_OFFSET(hostent, h_aliases);
223CHECK_SIZE_AND_OFFSET(hostent, h_addrtype);
224CHECK_SIZE_AND_OFFSET(hostent, h_length);
225CHECK_SIZE_AND_OFFSET(hostent, h_addr_list);
226
227CHECK_TYPE_SIZE(iovec);
228CHECK_SIZE_AND_OFFSET(iovec, iov_base);
229CHECK_SIZE_AND_OFFSET(iovec, iov_len);
230
231CHECK_TYPE_SIZE(msghdr);
232CHECK_SIZE_AND_OFFSET(msghdr, msg_name);
233CHECK_SIZE_AND_OFFSET(msghdr, msg_namelen);
234CHECK_SIZE_AND_OFFSET(msghdr, msg_iov);
235CHECK_SIZE_AND_OFFSET(msghdr, msg_iovlen);
236CHECK_SIZE_AND_OFFSET(msghdr, msg_control);
237CHECK_SIZE_AND_OFFSET(msghdr, msg_controllen);
238CHECK_SIZE_AND_OFFSET(msghdr, msg_flags);
239
240CHECK_TYPE_SIZE(cmsghdr);
241CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_len);
242CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_level);
243CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_type);
244
245COMPILER_CHECK(sizeof(__sanitizer_dirent) <= sizeof(dirent));
246CHECK_SIZE_AND_OFFSET(dirent, d_ino);
247CHECK_SIZE_AND_OFFSET(dirent, d_off);
248CHECK_SIZE_AND_OFFSET(dirent, d_reclen);
249
250#if SANITIZER_SOLARIS32
251COMPILER_CHECK(sizeof(__sanitizer_dirent64) <= sizeof(dirent64));
252CHECK_SIZE_AND_OFFSET(dirent64, d_ino);
253CHECK_SIZE_AND_OFFSET(dirent64, d_off);
254CHECK_SIZE_AND_OFFSET(dirent64, d_reclen);
255#endif
256
257CHECK_TYPE_SIZE(ifconf);
258CHECK_SIZE_AND_OFFSET(ifconf, ifc_len);
259CHECK_SIZE_AND_OFFSET(ifconf, ifc_ifcu);
260
261CHECK_TYPE_SIZE(pollfd);
262CHECK_SIZE_AND_OFFSET(pollfd, fd);
263CHECK_SIZE_AND_OFFSET(pollfd, events);
264CHECK_SIZE_AND_OFFSET(pollfd, revents);
265
266CHECK_TYPE_SIZE(nfds_t);
267
268CHECK_TYPE_SIZE(sigset_t);
269
270COMPILER_CHECK(sizeof(__sanitizer_sigaction) == sizeof(struct sigaction));
271// Can't write checks for sa_handler and sa_sigaction due to them being
272// preprocessor macros.
273CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_mask);
274CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_flags);
275
276CHECK_TYPE_SIZE(wordexp_t);
277CHECK_SIZE_AND_OFFSET(wordexp_t, we_wordc);
278CHECK_SIZE_AND_OFFSET(wordexp_t, we_wordv);
279CHECK_SIZE_AND_OFFSET(wordexp_t, we_offs);
280
281CHECK_TYPE_SIZE(tm);
282CHECK_SIZE_AND_OFFSET(tm, tm_sec);
283CHECK_SIZE_AND_OFFSET(tm, tm_min);
284CHECK_SIZE_AND_OFFSET(tm, tm_hour);
285CHECK_SIZE_AND_OFFSET(tm, tm_mday);
286CHECK_SIZE_AND_OFFSET(tm, tm_mon);
287CHECK_SIZE_AND_OFFSET(tm, tm_year);
288CHECK_SIZE_AND_OFFSET(tm, tm_wday);
289CHECK_SIZE_AND_OFFSET(tm, tm_yday);
290CHECK_SIZE_AND_OFFSET(tm, tm_isdst);
291
292CHECK_TYPE_SIZE(ether_addr);
293
294CHECK_TYPE_SIZE(ipc_perm);
295CHECK_SIZE_AND_OFFSET(ipc_perm, key);
296CHECK_SIZE_AND_OFFSET(ipc_perm, seq);
297CHECK_SIZE_AND_OFFSET(ipc_perm, uid);
298CHECK_SIZE_AND_OFFSET(ipc_perm, gid);
299CHECK_SIZE_AND_OFFSET(ipc_perm, cuid);
300CHECK_SIZE_AND_OFFSET(ipc_perm, cgid);
301CHECK_SIZE_AND_OFFSET(ipc_perm, mode);
302
303CHECK_TYPE_SIZE(shmid_ds);
304CHECK_SIZE_AND_OFFSET(shmid_ds, shm_perm);
305CHECK_SIZE_AND_OFFSET(shmid_ds, shm_segsz);
306CHECK_SIZE_AND_OFFSET(shmid_ds, shm_atime);
307CHECK_SIZE_AND_OFFSET(shmid_ds, shm_dtime);
308CHECK_SIZE_AND_OFFSET(shmid_ds, shm_ctime);
309CHECK_SIZE_AND_OFFSET(shmid_ds, shm_cpid);
310CHECK_SIZE_AND_OFFSET(shmid_ds, shm_lpid);
311CHECK_SIZE_AND_OFFSET(shmid_ds, shm_nattch);
312
313CHECK_TYPE_SIZE(clock_t);
314
315CHECK_TYPE_SIZE(ifaddrs);
316CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_next);
317CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_name);
318CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_addr);
319CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_netmask);
320// Compare against the union, because we can't reach into the union in a
321// compliant way.
322#ifdef ifa_dstaddr
323#undef ifa_dstaddr
324#endif
325COMPILER_CHECK(sizeof(((__sanitizer_ifaddrs *)nullptr)->ifa_dstaddr) ==
326 sizeof(((ifaddrs *)nullptr)->ifa_ifu));
327COMPILER_CHECK(offsetof(__sanitizer_ifaddrs, ifa_dstaddr) ==
328 offsetof(ifaddrs, ifa_ifu));
329CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_data);
330
331CHECK_TYPE_SIZE(timeb);
332CHECK_SIZE_AND_OFFSET(timeb, time);
333CHECK_SIZE_AND_OFFSET(timeb, millitm);
334CHECK_SIZE_AND_OFFSET(timeb, timezone);
335CHECK_SIZE_AND_OFFSET(timeb, dstflag);
336
337CHECK_TYPE_SIZE(passwd);
338CHECK_SIZE_AND_OFFSET(passwd, pw_name);
339CHECK_SIZE_AND_OFFSET(passwd, pw_passwd);
340CHECK_SIZE_AND_OFFSET(passwd, pw_uid);
341CHECK_SIZE_AND_OFFSET(passwd, pw_gid);
342CHECK_SIZE_AND_OFFSET(passwd, pw_dir);
343CHECK_SIZE_AND_OFFSET(passwd, pw_shell);
344
345CHECK_SIZE_AND_OFFSET(passwd, pw_gecos);
346
347CHECK_TYPE_SIZE(group);
348CHECK_SIZE_AND_OFFSET(group, gr_name);
349CHECK_SIZE_AND_OFFSET(group, gr_passwd);
350CHECK_SIZE_AND_OFFSET(group, gr_gid);
351CHECK_SIZE_AND_OFFSET(group, gr_mem);
352
353CHECK_TYPE_SIZE(XDR);
354CHECK_SIZE_AND_OFFSET(XDR, x_op);
355CHECK_SIZE_AND_OFFSET(XDR, x_ops);
356CHECK_SIZE_AND_OFFSET(XDR, x_public);
357CHECK_SIZE_AND_OFFSET(XDR, x_private);
358CHECK_SIZE_AND_OFFSET(XDR, x_base);
359CHECK_SIZE_AND_OFFSET(XDR, x_handy);
360COMPILER_CHECK(__sanitizer_XDR_ENCODE == XDR_ENCODE);
361COMPILER_CHECK(__sanitizer_XDR_DECODE == XDR_DECODE);
362COMPILER_CHECK(__sanitizer_XDR_FREE == XDR_FREE);
363
364CHECK_TYPE_SIZE(sem_t);
365
366#endif // SANITIZER_SOLARIS
lib/tsan/sanitizer_common/sanitizer_platform_limits_solaris.h created+495
...@@ -0,0 +1,495 @@
1//===-- sanitizer_platform_limits_solaris.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// Sizes and layouts of platform-specific Solaris data structures.
12//===----------------------------------------------------------------------===//
13
14#ifndef SANITIZER_PLATFORM_LIMITS_SOLARIS_H
15#define SANITIZER_PLATFORM_LIMITS_SOLARIS_H
16
17#if SANITIZER_SOLARIS
18
19#include "sanitizer_internal_defs.h"
20#include "sanitizer_platform.h"
21
22namespace __sanitizer {
23extern unsigned struct_utsname_sz;
24extern unsigned struct_stat_sz;
25extern unsigned struct_stat64_sz;
26extern unsigned struct_rusage_sz;
27extern unsigned siginfo_t_sz;
28extern unsigned struct_itimerval_sz;
29extern unsigned pthread_t_sz;
30extern unsigned pthread_mutex_t_sz;
31extern unsigned pthread_cond_t_sz;
32extern unsigned pid_t_sz;
33extern unsigned timeval_sz;
34extern unsigned uid_t_sz;
35extern unsigned gid_t_sz;
36extern unsigned mbstate_t_sz;
37extern unsigned struct_timezone_sz;
38extern unsigned struct_tms_sz;
39extern unsigned struct_itimerspec_sz;
40extern unsigned struct_sigevent_sz;
41extern unsigned struct_stack_t_sz;
42extern unsigned struct_sched_param_sz;
43extern unsigned struct_statfs64_sz;
44extern unsigned struct_statfs_sz;
45extern unsigned struct_sockaddr_sz;
46extern unsigned ucontext_t_sz;
47
48extern unsigned struct_timespec_sz;
49extern unsigned struct_rlimit_sz;
50extern unsigned struct_utimbuf_sz;
51
52struct __sanitizer_sem_t {
53 //u64 data[6];
54 u32 sem_count;
55 u16 sem_type;
56 u16 sem_magic;
57 u64 sem_pad1[3];
58 u64 sem_pad2[2];
59};
60
61struct __sanitizer_ipc_perm {
62 unsigned int uid; // uid_t
63 unsigned int gid; // gid_t
64 unsigned int cuid; // uid_t
65 unsigned int cgid; // gid_t
66 unsigned int mode; // mode_t
67 unsigned int seq; // uint_t
68 int key; // key_t
69#if !defined(_LP64)
70 int pad[4];
71#endif
72};
73
74struct __sanitizer_shmid_ds {
75 __sanitizer_ipc_perm shm_perm;
76 unsigned long shm_segsz; // size_t
77 unsigned long shm_flags; // uintptr_t
78 unsigned short shm_lkcnt; // ushort_t
79 int shm_lpid; // pid_t
80 int shm_cpid; // pid_t
81 unsigned long shm_nattch; // shmatt_t
82 unsigned long shm_cnattch; // ulong_t
83#if defined(_LP64)
84 long shm_atime; // time_t
85 long shm_dtime;
86 long shm_ctime;
87 void *shm_amp;
88 u64 shm_gransize; // uint64_t
89 u64 shm_allocated; // uint64_t
90 u64 shm_pad4[1]; // int64_t
91#else
92 long shm_atime; // time_t
93 int shm_pad1; // int32_t
94 long shm_dtime; // time_t
95 int shm_pad2; // int32_t
96 long shm_ctime; // time_t
97 void *shm_amp;
98 u64 shm_gransize; // uint64_t
99 u64 shm_allocated; // uint64_t
100#endif
101};
102
103extern unsigned struct_statvfs_sz;
104#if SANITIZER_SOLARIS32
105extern unsigned struct_statvfs64_sz;
106#endif
107
108struct __sanitizer_iovec {
109 void *iov_base;
110 uptr iov_len;
111};
112
113struct __sanitizer_ifaddrs {
114 struct __sanitizer_ifaddrs *ifa_next;
115 char *ifa_name;
116 u64 ifa_flags; // uint64_t
117 void *ifa_addr; // (struct sockaddr *)
118 void *ifa_netmask; // (struct sockaddr *)
119 // This is a union on Linux.
120# ifdef ifa_dstaddr
121# undef ifa_dstaddr
122# endif
123 void *ifa_dstaddr; // (struct sockaddr *)
124 void *ifa_data;
125};
126
127typedef unsigned __sanitizer_pthread_key_t;
128
129struct __sanitizer_XDR {
130 int x_op;
131 void *x_ops;
132 uptr x_public;
133 uptr x_private;
134 uptr x_base;
135 unsigned x_handy;
136};
137
138const int __sanitizer_XDR_ENCODE = 0;
139const int __sanitizer_XDR_DECODE = 1;
140const int __sanitizer_XDR_FREE = 2;
141
142struct __sanitizer_passwd {
143 char *pw_name;
144 char *pw_passwd;
145 unsigned int pw_uid; // uid_t
146 unsigned int pw_gid; // gid_t
147 char *pw_age;
148 char *pw_comment;
149 char *pw_gecos;
150 char *pw_dir;
151 char *pw_shell;
152};
153
154struct __sanitizer_group {
155 char *gr_name;
156 char *gr_passwd;
157 int gr_gid;
158 char **gr_mem;
159};
160
161typedef long __sanitizer_time_t;
162
163typedef long __sanitizer_suseconds_t;
164
165struct __sanitizer_timeval {
166 __sanitizer_time_t tv_sec;
167 __sanitizer_suseconds_t tv_usec;
168};
169
170struct __sanitizer_itimerval {
171 struct __sanitizer_timeval it_interval;
172 struct __sanitizer_timeval it_value;
173};
174
175struct __sanitizer_timeb {
176 __sanitizer_time_t time;
177 unsigned short millitm;
178 short timezone;
179 short dstflag;
180};
181
182struct __sanitizer_ether_addr {
183 u8 octet[6];
184};
185
186struct __sanitizer_tm {
187 int tm_sec;
188 int tm_min;
189 int tm_hour;
190 int tm_mday;
191 int tm_mon;
192 int tm_year;
193 int tm_wday;
194 int tm_yday;
195 int tm_isdst;
196};
197
198struct __sanitizer_msghdr {
199 void *msg_name;
200 unsigned msg_namelen;
201 struct __sanitizer_iovec *msg_iov;
202 unsigned msg_iovlen;
203 void *msg_control;
204 unsigned msg_controllen;
205 int msg_flags;
206};
207struct __sanitizer_cmsghdr {
208 unsigned cmsg_len;
209 int cmsg_level;
210 int cmsg_type;
211};
212
213#if SANITIZER_SOLARIS && (defined(_LP64) || _FILE_OFFSET_BITS == 64)
214struct __sanitizer_dirent {
215 unsigned long long d_ino;
216 long long d_off;
217 unsigned short d_reclen;
218 // more fields that we don't care about
219};
220#else
221struct __sanitizer_dirent {
222 unsigned long d_ino;
223 long d_off;
224 unsigned short d_reclen;
225 // more fields that we don't care about
226};
227#endif
228
229struct __sanitizer_dirent64 {
230 unsigned long long d_ino;
231 unsigned long long d_off;
232 unsigned short d_reclen;
233 // more fields that we don't care about
234};
235
236typedef long __sanitizer_clock_t;
237typedef int __sanitizer_clockid_t;
238
239// This thing depends on the platform. We are only interested in the upper
240// limit. Verified with a compiler assert in .cpp.
241union __sanitizer_pthread_attr_t {
242 char size[128];
243 void *align;
244};
245
246struct __sanitizer_sigset_t {
247 // uint32_t * 4
248 unsigned int __bits[4];
249};
250
251struct __sanitizer_siginfo {
252 // The size is determined by looking at sizeof of real siginfo_t on linux.
253 u64 opaque[128 / sizeof(u64)];
254};
255
256using __sanitizer_sighandler_ptr = void (*)(int sig);
257using __sanitizer_sigactionhandler_ptr =
258 void (*)(int sig, __sanitizer_siginfo *siginfo, void *uctx);
259
260struct __sanitizer_sigaction {
261 int sa_flags;
262 union {
263 __sanitizer_sigactionhandler_ptr sigaction;
264 __sanitizer_sighandler_ptr handler;
265 };
266 __sanitizer_sigset_t sa_mask;
267#if !defined(_LP64)
268 int sa_resv[2];
269#endif
270};
271
272struct __sanitizer_kernel_sigset_t {
273 u8 sig[8];
274};
275
276struct __sanitizer_kernel_sigaction_t {
277 union {
278 void (*handler)(int signo);
279 void (*sigaction)(int signo, __sanitizer_siginfo *info, void *ctx);
280 };
281 unsigned long sa_flags;
282 void (*sa_restorer)(void);
283 __sanitizer_kernel_sigset_t sa_mask;
284};
285
286extern const uptr sig_ign;
287extern const uptr sig_dfl;
288extern const uptr sig_err;
289extern const uptr sa_siginfo;
290
291extern int af_inet;
292extern int af_inet6;
293uptr __sanitizer_in_addr_sz(int af);
294
295struct __sanitizer_dl_phdr_info {
296 uptr dlpi_addr;
297 const char *dlpi_name;
298 const void *dlpi_phdr;
299 short dlpi_phnum;
300};
301
302extern unsigned struct_ElfW_Phdr_sz;
303
304struct __sanitizer_addrinfo {
305 int ai_flags;
306 int ai_family;
307 int ai_socktype;
308 int ai_protocol;
309#if defined(__sparcv9)
310 int _ai_pad;
311#endif
312 unsigned ai_addrlen;
313 char *ai_canonname;
314 void *ai_addr;
315 struct __sanitizer_addrinfo *ai_next;
316};
317
318struct __sanitizer_hostent {
319 char *h_name;
320 char **h_aliases;
321 int h_addrtype;
322 int h_length;
323 char **h_addr_list;
324};
325
326struct __sanitizer_pollfd {
327 int fd;
328 short events;
329 short revents;
330};
331
332typedef unsigned long __sanitizer_nfds_t;
333
334struct __sanitizer_glob_t {
335 uptr gl_pathc;
336 char **gl_pathv;
337 uptr gl_offs;
338 char **gl_pathp;
339 int gl_pathn;
340};
341
342extern int glob_nomatch;
343extern int glob_altdirfunc;
344
345extern unsigned path_max;
346
347struct __sanitizer_wordexp_t {
348 uptr we_wordc;
349 char **we_wordv;
350 uptr we_offs;
351 char **we_wordp;
352 int we_wordn;
353};
354
355typedef void __sanitizer_FILE;
356#define SANITIZER_HAS_STRUCT_FILE 0
357
358// This simplifies generic code
359#define struct_shminfo_sz -1
360#define struct_shm_info_sz -1
361#define shmctl_shm_stat -1
362#define shmctl_ipc_info -1
363#define shmctl_shm_info -1
364
365extern int shmctl_ipc_stat;
366
367extern unsigned struct_utmp_sz;
368extern unsigned struct_utmpx_sz;
369
370extern int map_fixed;
371
372// ioctl arguments
373struct __sanitizer_ifconf {
374 int ifc_len;
375 union {
376 void *ifcu_req;
377 } ifc_ifcu;
378};
379
380// <sys/ioccom.h>
381#define IOC_NRBITS 8
382#define IOC_TYPEBITS 8
383#define IOC_SIZEBITS 12
384#define IOC_DIRBITS 4
385#undef IOC_NONE
386#define IOC_NONE 2U // IOC_VOID
387#define IOC_READ 4U // IOC_OUT
388#define IOC_WRITE 8U // IOC_IN
389
390#define IOC_NRMASK ((1 << IOC_NRBITS) - 1)
391#define IOC_TYPEMASK ((1 << IOC_TYPEBITS) - 1)
392#define IOC_SIZEMASK ((1 << IOC_SIZEBITS) - 1)
393#define IOC_DIRMASK ((1 << IOC_DIRBITS) - 1)
394#define IOC_NRSHIFT 0
395#define IOC_TYPESHIFT (IOC_NRSHIFT + IOC_NRBITS)
396#define IOC_SIZESHIFT (IOC_TYPESHIFT + IOC_TYPEBITS)
397#define IOC_DIRSHIFT (IOC_SIZESHIFT + IOC_SIZEBITS)
398
399#define IOC_DIR(nr) (((nr) >> IOC_DIRSHIFT) & IOC_DIRMASK)
400#define IOC_TYPE(nr) (((nr) >> IOC_TYPESHIFT) & IOC_TYPEMASK)
401#define IOC_NR(nr) (((nr) >> IOC_NRSHIFT) & IOC_NRMASK)
402
403#if defined(__sparc__)
404// In sparc the 14 bits SIZE field overlaps with the
405// least significant bit of DIR, so either IOC_READ or
406// IOC_WRITE shall be 1 in order to get a non-zero SIZE.
407#define IOC_SIZE(nr) \
408 ((((((nr) >> 29) & 0x7) & (4U | 2U)) == 0) ? 0 : (((nr) >> 16) & 0x3fff))
409#else
410#define IOC_SIZE(nr) (((nr) >> IOC_SIZESHIFT) & IOC_SIZEMASK)
411#endif
412
413extern unsigned struct_ifreq_sz;
414extern unsigned struct_termios_sz;
415extern unsigned struct_winsize_sz;
416
417extern unsigned struct_sioc_sg_req_sz;
418extern unsigned struct_sioc_vif_req_sz;
419
420// ioctl request identifiers
421
422// A special value to mark ioctls that are not present on the target platform,
423// when it can not be determined without including any system headers.
424extern const unsigned IOCTL_NOT_PRESENT;
425
426extern unsigned IOCTL_FIOASYNC;
427extern unsigned IOCTL_FIOCLEX;
428extern unsigned IOCTL_FIOGETOWN;
429extern unsigned IOCTL_FIONBIO;
430extern unsigned IOCTL_FIONCLEX;
431extern unsigned IOCTL_FIOSETOWN;
432extern unsigned IOCTL_SIOCADDMULTI;
433extern unsigned IOCTL_SIOCATMARK;
434extern unsigned IOCTL_SIOCDELMULTI;
435extern unsigned IOCTL_SIOCGIFADDR;
436extern unsigned IOCTL_SIOCGIFBRDADDR;
437extern unsigned IOCTL_SIOCGIFCONF;
438extern unsigned IOCTL_SIOCGIFDSTADDR;
439extern unsigned IOCTL_SIOCGIFFLAGS;
440extern unsigned IOCTL_SIOCGIFMETRIC;
441extern unsigned IOCTL_SIOCGIFMTU;
442extern unsigned IOCTL_SIOCGIFNETMASK;
443extern unsigned IOCTL_SIOCGPGRP;
444extern unsigned IOCTL_SIOCSIFADDR;
445extern unsigned IOCTL_SIOCSIFBRDADDR;
446extern unsigned IOCTL_SIOCSIFDSTADDR;
447extern unsigned IOCTL_SIOCSIFFLAGS;
448extern unsigned IOCTL_SIOCSIFMETRIC;
449extern unsigned IOCTL_SIOCSIFMTU;
450extern unsigned IOCTL_SIOCSIFNETMASK;
451extern unsigned IOCTL_SIOCSPGRP;
452extern unsigned IOCTL_TIOCEXCL;
453extern unsigned IOCTL_TIOCGETD;
454extern unsigned IOCTL_TIOCGPGRP;
455extern unsigned IOCTL_TIOCGWINSZ;
456extern unsigned IOCTL_TIOCMBIC;
457extern unsigned IOCTL_TIOCMBIS;
458extern unsigned IOCTL_TIOCMGET;
459extern unsigned IOCTL_TIOCMSET;
460extern unsigned IOCTL_TIOCNOTTY;
461extern unsigned IOCTL_TIOCNXCL;
462extern unsigned IOCTL_TIOCOUTQ;
463extern unsigned IOCTL_TIOCPKT;
464extern unsigned IOCTL_TIOCSCTTY;
465extern unsigned IOCTL_TIOCSETD;
466extern unsigned IOCTL_TIOCSPGRP;
467extern unsigned IOCTL_TIOCSTI;
468extern unsigned IOCTL_TIOCSWINSZ;
469extern unsigned IOCTL_MTIOCGET;
470extern unsigned IOCTL_MTIOCTOP;
471
472extern const int si_SEGV_MAPERR;
473extern const int si_SEGV_ACCERR;
474} // namespace __sanitizer
475
476#define CHECK_TYPE_SIZE(TYPE) \
477 COMPILER_CHECK(sizeof(__sanitizer_##TYPE) == sizeof(TYPE))
478
479#define CHECK_SIZE_AND_OFFSET(CLASS, MEMBER) \
480 COMPILER_CHECK(sizeof(((__sanitizer_##CLASS *) NULL)->MEMBER) == \
481 sizeof(((CLASS *) NULL)->MEMBER)); \
482 COMPILER_CHECK(offsetof(__sanitizer_##CLASS, MEMBER) == \
483 offsetof(CLASS, MEMBER))
484
485// For sigaction, which is a function and struct at the same time,
486// and thus requires explicit "struct" in sizeof() expression.
487#define CHECK_STRUCT_SIZE_AND_OFFSET(CLASS, MEMBER) \
488 COMPILER_CHECK(sizeof(((struct __sanitizer_##CLASS *) NULL)->MEMBER) == \
489 sizeof(((struct CLASS *) NULL)->MEMBER)); \
490 COMPILER_CHECK(offsetof(struct __sanitizer_##CLASS, MEMBER) == \
491 offsetof(struct CLASS, MEMBER))
492
493#endif // SANITIZER_SOLARIS
494
495#endif
lib/tsan/sanitizer_common/sanitizer_posix.cpp created+398
...@@ -0,0 +1,398 @@
1//===-- sanitizer_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 shared between AddressSanitizer and ThreadSanitizer
10// run-time libraries and implements POSIX-specific functions from
11// sanitizer_posix.h.
12//===----------------------------------------------------------------------===//
13
14#include "sanitizer_platform.h"
15
16#if SANITIZER_POSIX
17
18#include "sanitizer_common.h"
19#include "sanitizer_file.h"
20#include "sanitizer_flags.h"
21#include "sanitizer_libc.h"
22#include "sanitizer_posix.h"
23#include "sanitizer_procmaps.h"
24
25#include <errno.h>
26#include <fcntl.h>
27#include <signal.h>
28#include <sys/mman.h>
29
30#if SANITIZER_FREEBSD
31// The MAP_NORESERVE define has been removed in FreeBSD 11.x, and even before
32// that, it was never implemented. So just define it to zero.
33#undef MAP_NORESERVE
34#define MAP_NORESERVE 0
35#endif
36
37namespace __sanitizer {
38
39// ------------- sanitizer_common.h
40uptr GetMmapGranularity() {
41 return GetPageSize();
42}
43
44void *MmapOrDie(uptr size, const char *mem_type, bool raw_report) {
45 size = RoundUpTo(size, GetPageSizeCached());
46 uptr res = MmapNamed(nullptr, size, PROT_READ | PROT_WRITE,
47 MAP_PRIVATE | MAP_ANON, mem_type);
48 int reserrno;
49 if (UNLIKELY(internal_iserror(res, &reserrno)))
50 ReportMmapFailureAndDie(size, mem_type, "allocate", reserrno, raw_report);
51 IncreaseTotalMmap(size);
52 return (void *)res;
53}
54
55void UnmapOrDie(void *addr, uptr size) {
56 if (!addr || !size) return;
57 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 }
63 DecreaseTotalMmap(size);
64}
65
66void *MmapOrDieOnFatalError(uptr size, const char *mem_type) {
67 size = RoundUpTo(size, GetPageSizeCached());
68 uptr res = MmapNamed(nullptr, size, PROT_READ | PROT_WRITE,
69 MAP_PRIVATE | MAP_ANON, mem_type);
70 int reserrno;
71 if (UNLIKELY(internal_iserror(res, &reserrno))) {
72 if (reserrno == ENOMEM)
73 return nullptr;
74 ReportMmapFailureAndDie(size, mem_type, "allocate", reserrno);
75 }
76 IncreaseTotalMmap(size);
77 return (void *)res;
78}
79
80// We want to map a chunk of address space aligned to 'alignment'.
81// We do it by mapping a bit more and then unmapping redundant pieces.
82// We probably can do it with fewer syscalls in some OS-dependent way.
83void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment,
84 const char *mem_type) {
85 CHECK(IsPowerOfTwo(size));
86 CHECK(IsPowerOfTwo(alignment));
87 uptr map_size = size + alignment;
88 uptr map_res = (uptr)MmapOrDieOnFatalError(map_size, mem_type);
89 if (UNLIKELY(!map_res))
90 return nullptr;
91 uptr map_end = map_res + map_size;
92 uptr res = map_res;
93 if (!IsAligned(res, alignment)) {
94 res = (map_res + alignment - 1) & ~(alignment - 1);
95 UnmapOrDie((void*)map_res, res - map_res);
96 }
97 uptr end = res + size;
98 if (end != map_end)
99 UnmapOrDie((void*)end, map_end - end);
100 return (void*)res;
101}
102
103void *MmapNoReserveOrDie(uptr size, const char *mem_type) {
104 size = RoundUpTo(size, GetPageSizeCached());
105 uptr p = MmapNamed(nullptr, size, PROT_READ | PROT_WRITE,
106 MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, mem_type);
107 int reserrno;
108 if (UNLIKELY(internal_iserror(p, &reserrno)))
109 ReportMmapFailureAndDie(size, mem_type, "allocate noreserve", reserrno);
110 IncreaseTotalMmap(size);
111 return (void *)p;
112}
113
114static void *MmapFixedImpl(uptr fixed_addr, uptr size, bool tolerate_enomem,
115 const char *name) {
116 size = RoundUpTo(size, GetPageSizeCached());
117 fixed_addr = RoundDownTo(fixed_addr, GetPageSizeCached());
118 uptr p = MmapNamed((void *)fixed_addr, size, PROT_READ | PROT_WRITE,
119 MAP_PRIVATE | MAP_ANON | MAP_FIXED, name);
120 int reserrno;
121 if (UNLIKELY(internal_iserror(p, &reserrno))) {
122 if (tolerate_enomem && reserrno == ENOMEM)
123 return nullptr;
124 char mem_type[40];
125 internal_snprintf(mem_type, sizeof(mem_type), "memory at address 0x%zx",
126 fixed_addr);
127 ReportMmapFailureAndDie(size, mem_type, "allocate", reserrno);
128 }
129 IncreaseTotalMmap(size);
130 return (void *)p;
131}
132
133void *MmapFixedOrDie(uptr fixed_addr, uptr size, const char *name) {
134 return MmapFixedImpl(fixed_addr, size, false /*tolerate_enomem*/, name);
135}
136
137void *MmapFixedOrDieOnFatalError(uptr fixed_addr, uptr size, const char *name) {
138 return MmapFixedImpl(fixed_addr, size, true /*tolerate_enomem*/, name);
139}
140
141bool MprotectNoAccess(uptr addr, uptr size) {
142 return 0 == internal_mprotect((void*)addr, size, PROT_NONE);
143}
144
145bool MprotectReadOnly(uptr addr, uptr size) {
146 return 0 == internal_mprotect((void *)addr, size, PROT_READ);
147}
148
149#if !SANITIZER_MAC
150void MprotectMallocZones(void *addr, int prot) {}
151#endif
152
153fd_t OpenFile(const char *filename, FileAccessMode mode, error_t *errno_p) {
154 if (ShouldMockFailureToOpen(filename))
155 return kInvalidFd;
156 int flags;
157 switch (mode) {
158 case RdOnly: flags = O_RDONLY; break;
159 case WrOnly: flags = O_WRONLY | O_CREAT | O_TRUNC; break;
160 case RdWr: flags = O_RDWR | O_CREAT; break;
161 }
162 fd_t res = internal_open(filename, flags, 0660);
163 if (internal_iserror(res, errno_p))
164 return kInvalidFd;
165 return ReserveStandardFds(res);
166}
167
168void CloseFile(fd_t fd) {
169 internal_close(fd);
170}
171
172bool ReadFromFile(fd_t fd, void *buff, uptr buff_size, uptr *bytes_read,
173 error_t *error_p) {
174 uptr res = internal_read(fd, buff, buff_size);
175 if (internal_iserror(res, error_p))
176 return false;
177 if (bytes_read)
178 *bytes_read = res;
179 return true;
180}
181
182bool WriteToFile(fd_t fd, const void *buff, uptr buff_size, uptr *bytes_written,
183 error_t *error_p) {
184 uptr res = internal_write(fd, buff, buff_size);
185 if (internal_iserror(res, error_p))
186 return false;
187 if (bytes_written)
188 *bytes_written = res;
189 return true;
190}
191
192void *MapFileToMemory(const char *file_name, uptr *buff_size) {
193 fd_t fd = OpenFile(file_name, RdOnly);
194 CHECK(fd != kInvalidFd);
195 uptr fsize = internal_filesize(fd);
196 CHECK_NE(fsize, (uptr)-1);
197 CHECK_GT(fsize, 0);
198 *buff_size = RoundUpTo(fsize, GetPageSizeCached());
199 uptr map = internal_mmap(nullptr, *buff_size, PROT_READ, MAP_PRIVATE, fd, 0);
200 return internal_iserror(map) ? nullptr : (void *)map;
201}
202
203void *MapWritableFileToMemory(void *addr, uptr size, fd_t fd, OFF_T offset) {
204 uptr flags = MAP_SHARED;
205 if (addr) flags |= MAP_FIXED;
206 uptr p = internal_mmap(addr, size, PROT_READ | PROT_WRITE, flags, fd, offset);
207 int mmap_errno = 0;
208 if (internal_iserror(p, &mmap_errno)) {
209 Printf("could not map writable file (%d, %lld, %zu): %zd, errno: %d\n",
210 fd, (long long)offset, size, p, mmap_errno);
211 return nullptr;
212 }
213 return (void *)p;
214}
215
216static inline bool IntervalsAreSeparate(uptr start1, uptr end1,
217 uptr start2, uptr end2) {
218 CHECK(start1 <= end1);
219 CHECK(start2 <= end2);
220 return (end1 < start2) || (end2 < start1);
221}
222
223// FIXME: this is thread-unsafe, but should not cause problems most of the time.
224// When the shadow is mapped only a single thread usually exists (plus maybe
225// several worker threads on Mac, which aren't expected to map big chunks of
226// memory).
227bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) {
228 MemoryMappingLayout proc_maps(/*cache_enabled*/true);
229 if (proc_maps.Error())
230 return true; // and hope for the best
231 MemoryMappedSegment segment;
232 while (proc_maps.Next(&segment)) {
233 if (segment.start == segment.end) continue; // Empty range.
234 CHECK_NE(0, segment.end);
235 if (!IntervalsAreSeparate(segment.start, segment.end - 1, range_start,
236 range_end))
237 return false;
238 }
239 return true;
240}
241
242void DumpProcessMap() {
243 MemoryMappingLayout proc_maps(/*cache_enabled*/true);
244 const sptr kBufSize = 4095;
245 char *filename = (char*)MmapOrDie(kBufSize, __func__);
246 MemoryMappedSegment segment(filename, kBufSize);
247 Report("Process memory map follows:\n");
248 while (proc_maps.Next(&segment)) {
249 Printf("\t%p-%p\t%s\n", (void *)segment.start, (void *)segment.end,
250 segment.filename);
251 }
252 Report("End of process memory map.\n");
253 UnmapOrDie(filename, kBufSize);
254}
255
256const char *GetPwd() {
257 return GetEnv("PWD");
258}
259
260bool IsPathSeparator(const char c) {
261 return c == '/';
262}
263
264bool IsAbsolutePath(const char *path) {
265 return path != nullptr && IsPathSeparator(path[0]);
266}
267
268void ReportFile::Write(const char *buffer, uptr length) {
269 SpinMutexLock l(mu);
270 ReopenIfNecessary();
271 internal_write(fd, buffer, length);
272}
273
274bool GetCodeRangeForFile(const char *module, uptr *start, uptr *end) {
275 MemoryMappingLayout proc_maps(/*cache_enabled*/false);
276 InternalScopedString buff(kMaxPathLength);
277 MemoryMappedSegment segment(buff.data(), kMaxPathLength);
278 while (proc_maps.Next(&segment)) {
279 if (segment.IsExecutable() &&
280 internal_strcmp(module, segment.filename) == 0) {
281 *start = segment.start;
282 *end = segment.end;
283 return true;
284 }
285 }
286 return false;
287}
288
289uptr SignalContext::GetAddress() const {
290 auto si = static_cast<const siginfo_t *>(siginfo);
291 return (uptr)si->si_addr;
292}
293
294bool SignalContext::IsMemoryAccess() const {
295 auto si = static_cast<const siginfo_t *>(siginfo);
296 return si->si_signo == SIGSEGV;
297}
298
299int SignalContext::GetType() const {
300 return static_cast<const siginfo_t *>(siginfo)->si_signo;
301}
302
303const char *SignalContext::Describe() const {
304 switch (GetType()) {
305 case SIGFPE:
306 return "FPE";
307 case SIGILL:
308 return "ILL";
309 case SIGABRT:
310 return "ABRT";
311 case SIGSEGV:
312 return "SEGV";
313 case SIGBUS:
314 return "BUS";
315 case SIGTRAP:
316 return "TRAP";
317 }
318 return "UNKNOWN SIGNAL";
319}
320
321fd_t ReserveStandardFds(fd_t fd) {
322 CHECK_GE(fd, 0);
323 if (fd > 2)
324 return fd;
325 bool used[3];
326 internal_memset(used, 0, sizeof(used));
327 while (fd <= 2) {
328 used[fd] = true;
329 fd = internal_dup(fd);
330 }
331 for (int i = 0; i <= 2; ++i)
332 if (used[i])
333 internal_close(i);
334 return fd;
335}
336
337bool ShouldMockFailureToOpen(const char *path) {
338 return common_flags()->test_only_emulate_no_memorymap &&
339 internal_strncmp(path, "/proc/", 6) == 0;
340}
341
342#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_GO
343int GetNamedMappingFd(const char *name, uptr size, int *flags) {
344 if (!common_flags()->decorate_proc_maps || !name)
345 return -1;
346 char shmname[200];
347 CHECK(internal_strlen(name) < sizeof(shmname) - 10);
348 internal_snprintf(shmname, sizeof(shmname), "/dev/shm/%zu [%s]",
349 internal_getpid(), name);
350 int o_cloexec = 0;
351#if defined(O_CLOEXEC)
352 o_cloexec = O_CLOEXEC;
353#endif
354 int fd = ReserveStandardFds(
355 internal_open(shmname, O_RDWR | O_CREAT | O_TRUNC | o_cloexec, S_IRWXU));
356 CHECK_GE(fd, 0);
357 if (!o_cloexec) {
358 int res = fcntl(fd, F_SETFD, FD_CLOEXEC);
359 CHECK_EQ(0, res);
360 }
361 int res = internal_ftruncate(fd, size);
362 CHECK_EQ(0, res);
363 res = internal_unlink(shmname);
364 CHECK_EQ(0, res);
365 *flags &= ~(MAP_ANON | MAP_ANONYMOUS);
366 return fd;
367}
368#else
369int GetNamedMappingFd(const char *name, uptr size, int *flags) {
370 return -1;
371}
372#endif
373
374#if SANITIZER_ANDROID
375#define PR_SET_VMA 0x53564d41
376#define PR_SET_VMA_ANON_NAME 0
377void DecorateMapping(uptr addr, uptr size, const char *name) {
378 if (!common_flags()->decorate_proc_maps || !name)
379 return;
380 internal_prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, addr, size, (uptr)name);
381}
382#else
383void DecorateMapping(uptr addr, uptr size, const char *name) {
384}
385#endif
386
387uptr MmapNamed(void *addr, uptr length, int prot, int flags, const char *name) {
388 int fd = GetNamedMappingFd(name, length, &flags);
389 uptr res = internal_mmap(addr, length, prot, flags, fd, 0);
390 if (!internal_iserror(res))
391 DecorateMapping(res, length, name);
392 return res;
393}
394
395
396} // namespace __sanitizer
397
398#endif // SANITIZER_POSIX
lib/tsan/sanitizer_common/sanitizer_posix.h created+125
...@@ -0,0 +1,125 @@
1//===-- sanitizer_posix.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 shared between AddressSanitizer and ThreadSanitizer
10// run-time libraries and declares some useful POSIX-specific functions.
11//===----------------------------------------------------------------------===//
12#ifndef SANITIZER_POSIX_H
13#define SANITIZER_POSIX_H
14
15// ----------- ATTENTION -------------
16// This header should NOT include any other headers from sanitizer runtime.
17#include "sanitizer_internal_defs.h"
18#include "sanitizer_platform_limits_freebsd.h"
19#include "sanitizer_platform_limits_netbsd.h"
20#include "sanitizer_platform_limits_openbsd.h"
21#include "sanitizer_platform_limits_posix.h"
22#include "sanitizer_platform_limits_solaris.h"
23
24#if !SANITIZER_POSIX
25// Make it hard to accidentally use any of functions declared in this file:
26#error This file should only be included on POSIX
27#endif
28
29namespace __sanitizer {
30
31// I/O
32// Don't use directly, use __sanitizer::OpenFile() instead.
33uptr internal_open(const char *filename, int flags);
34uptr internal_open(const char *filename, int flags, u32 mode);
35uptr internal_close(fd_t fd);
36
37uptr internal_read(fd_t fd, void *buf, uptr count);
38uptr internal_write(fd_t fd, const void *buf, uptr count);
39
40// Memory
41uptr internal_mmap(void *addr, uptr length, int prot, int flags,
42 int fd, u64 offset);
43uptr internal_munmap(void *addr, uptr length);
44int internal_mprotect(void *addr, uptr length, int prot);
45
46// OS
47uptr internal_filesize(fd_t fd); // -1 on error.
48uptr internal_stat(const char *path, void *buf);
49uptr internal_lstat(const char *path, void *buf);
50uptr internal_fstat(fd_t fd, void *buf);
51uptr internal_dup(int oldfd);
52uptr internal_dup2(int oldfd, int newfd);
53uptr internal_readlink(const char *path, char *buf, uptr bufsize);
54uptr internal_unlink(const char *path);
55uptr internal_rename(const char *oldpath, const char *newpath);
56uptr internal_lseek(fd_t fd, OFF_T offset, int whence);
57
58#if SANITIZER_NETBSD
59uptr internal_ptrace(int request, int pid, void *addr, int data);
60#else
61uptr internal_ptrace(int request, int pid, void *addr, void *data);
62#endif
63uptr internal_waitpid(int pid, int *status, int options);
64
65int internal_fork();
66fd_t internal_spawn(const char *argv[], const char *envp[], pid_t *pid);
67
68int internal_sysctl(const int *name, unsigned int namelen, void *oldp,
69 uptr *oldlenp, const void *newp, uptr newlen);
70int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp,
71 const void *newp, uptr newlen);
72
73// These functions call appropriate pthread_ functions directly, bypassing
74// the interceptor. They are weak and may not be present in some tools.
75SANITIZER_WEAK_ATTRIBUTE
76int real_pthread_create(void *th, void *attr, void *(*callback)(void *),
77 void *param);
78SANITIZER_WEAK_ATTRIBUTE
79int real_pthread_join(void *th, void **ret);
80
81#define DEFINE_REAL_PTHREAD_FUNCTIONS \
82 namespace __sanitizer { \
83 int real_pthread_create(void *th, void *attr, void *(*callback)(void *), \
84 void *param) { \
85 return REAL(pthread_create)(th, attr, callback, param); \
86 } \
87 int real_pthread_join(void *th, void **ret) { \
88 return REAL(pthread_join(th, ret)); \
89 } \
90 } // namespace __sanitizer
91
92int my_pthread_attr_getstack(void *attr, void **addr, uptr *size);
93
94// A routine named real_sigaction() must be implemented by each sanitizer in
95// order for internal_sigaction() to bypass interceptors.
96int internal_sigaction(int signum, const void *act, void *oldact);
97void internal_sigfillset(__sanitizer_sigset_t *set);
98void internal_sigemptyset(__sanitizer_sigset_t *set);
99bool internal_sigismember(__sanitizer_sigset_t *set, int signum);
100
101uptr internal_execve(const char *filename, char *const argv[],
102 char *const envp[]);
103
104bool IsStateDetached(int state);
105
106// Move the fd out of {0, 1, 2} range.
107fd_t ReserveStandardFds(fd_t fd);
108
109bool ShouldMockFailureToOpen(const char *path);
110
111// Create a non-file mapping with a given /proc/self/maps name.
112uptr MmapNamed(void *addr, uptr length, int prot, int flags, const char *name);
113
114// Platforms should implement at most one of these.
115// 1. Provide a pre-decorated file descriptor to use instead of an anonymous
116// mapping.
117int GetNamedMappingFd(const char *name, uptr size, int *flags);
118// 2. Add name to an existing anonymous mapping. The caller must keep *name
119// alive at least as long as the mapping exists.
120void DecorateMapping(uptr addr, uptr size, const char *name);
121
122
123} // namespace __sanitizer
124
125#endif // SANITIZER_POSIX_H
lib/tsan/sanitizer_common/sanitizer_printf.cpp created+358
...@@ -0,0 +1,358 @@
1//===-- sanitizer_printf.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 shared between AddressSanitizer and ThreadSanitizer.
10//
11// Internal printf function, used inside run-time libraries.
12// We can't use libc printf because we intercept some of the functions used
13// inside it.
14//===----------------------------------------------------------------------===//
15
16#include "sanitizer_common.h"
17#include "sanitizer_flags.h"
18#include "sanitizer_libc.h"
19
20#include <stdio.h>
21#include <stdarg.h>
22
23#if SANITIZER_WINDOWS && defined(_MSC_VER) && _MSC_VER < 1800 && \
24 !defined(va_copy)
25# define va_copy(dst, src) ((dst) = (src))
26#endif
27
28namespace __sanitizer {
29
30static int AppendChar(char **buff, const char *buff_end, char c) {
31 if (*buff < buff_end) {
32 **buff = c;
33 (*buff)++;
34 }
35 return 1;
36}
37
38// Appends number in a given base to buffer. If its length is less than
39// |minimal_num_length|, it is padded with leading zeroes or spaces, depending
40// on the value of |pad_with_zero|.
41static int AppendNumber(char **buff, const char *buff_end, u64 absolute_value,
42 u8 base, u8 minimal_num_length, bool pad_with_zero,
43 bool negative, bool uppercase) {
44 uptr const kMaxLen = 30;
45 RAW_CHECK(base == 10 || base == 16);
46 RAW_CHECK(base == 10 || !negative);
47 RAW_CHECK(absolute_value || !negative);
48 RAW_CHECK(minimal_num_length < kMaxLen);
49 int result = 0;
50 if (negative && minimal_num_length)
51 --minimal_num_length;
52 if (negative && pad_with_zero)
53 result += AppendChar(buff, buff_end, '-');
54 uptr num_buffer[kMaxLen];
55 int pos = 0;
56 do {
57 RAW_CHECK_MSG((uptr)pos < kMaxLen, "AppendNumber buffer overflow");
58 num_buffer[pos++] = absolute_value % base;
59 absolute_value /= base;
60 } while (absolute_value > 0);
61 if (pos < minimal_num_length) {
62 // Make sure compiler doesn't insert call to memset here.
63 internal_memset(&num_buffer[pos], 0,
64 sizeof(num_buffer[0]) * (minimal_num_length - pos));
65 pos = minimal_num_length;
66 }
67 RAW_CHECK(pos > 0);
68 pos--;
69 for (; pos >= 0 && num_buffer[pos] == 0; pos--) {
70 char c = (pad_with_zero || pos == 0) ? '0' : ' ';
71 result += AppendChar(buff, buff_end, c);
72 }
73 if (negative && !pad_with_zero) result += AppendChar(buff, buff_end, '-');
74 for (; pos >= 0; pos--) {
75 char digit = static_cast<char>(num_buffer[pos]);
76 digit = (digit < 10) ? '0' + digit : (uppercase ? 'A' : 'a') + digit - 10;
77 result += AppendChar(buff, buff_end, digit);
78 }
79 return result;
80}
81
82static int AppendUnsigned(char **buff, const char *buff_end, u64 num, u8 base,
83 u8 minimal_num_length, bool pad_with_zero,
84 bool uppercase) {
85 return AppendNumber(buff, buff_end, num, base, minimal_num_length,
86 pad_with_zero, false /* negative */, uppercase);
87}
88
89static int AppendSignedDecimal(char **buff, const char *buff_end, s64 num,
90 u8 minimal_num_length, bool pad_with_zero) {
91 bool negative = (num < 0);
92 return AppendNumber(buff, buff_end, (u64)(negative ? -num : num), 10,
93 minimal_num_length, pad_with_zero, negative,
94 false /* uppercase */);
95}
96
97
98// Use the fact that explicitly requesting 0 width (%0s) results in UB and
99// interpret width == 0 as "no width requested":
100// width == 0 - no width requested
101// width < 0 - left-justify s within and pad it to -width chars, if necessary
102// width > 0 - right-justify s, not implemented yet
103static int AppendString(char **buff, const char *buff_end, int width,
104 int max_chars, const char *s) {
105 if (!s)
106 s = "<null>";
107 int result = 0;
108 for (; *s; s++) {
109 if (max_chars >= 0 && result >= max_chars)
110 break;
111 result += AppendChar(buff, buff_end, *s);
112 }
113 // Only the left justified strings are supported.
114 while (width < -result)
115 result += AppendChar(buff, buff_end, ' ');
116 return result;
117}
118
119static int AppendPointer(char **buff, const char *buff_end, u64 ptr_value) {
120 int result = 0;
121 result += AppendString(buff, buff_end, 0, -1, "0x");
122 result += AppendUnsigned(buff, buff_end, ptr_value, 16,
123 SANITIZER_POINTER_FORMAT_LENGTH,
124 true /* pad_with_zero */, false /* uppercase */);
125 return result;
126}
127
128int VSNPrintf(char *buff, int buff_length,
129 const char *format, va_list args) {
130 static const char *kPrintfFormatsHelp =
131 "Supported Printf formats: %([0-9]*)?(z|ll)?{d,u,x,X}; %p; "
132 "%[-]([0-9]*)?(\\.\\*)?s; %c\n";
133 RAW_CHECK(format);
134 RAW_CHECK(buff_length > 0);
135 const char *buff_end = &buff[buff_length - 1];
136 const char *cur = format;
137 int result = 0;
138 for (; *cur; cur++) {
139 if (*cur != '%') {
140 result += AppendChar(&buff, buff_end, *cur);
141 continue;
142 }
143 cur++;
144 bool left_justified = *cur == '-';
145 if (left_justified)
146 cur++;
147 bool have_width = (*cur >= '0' && *cur <= '9');
148 bool pad_with_zero = (*cur == '0');
149 int width = 0;
150 if (have_width) {
151 while (*cur >= '0' && *cur <= '9') {
152 width = width * 10 + *cur++ - '0';
153 }
154 }
155 bool have_precision = (cur[0] == '.' && cur[1] == '*');
156 int precision = -1;
157 if (have_precision) {
158 cur += 2;
159 precision = va_arg(args, int);
160 }
161 bool have_z = (*cur == 'z');
162 cur += have_z;
163 bool have_ll = !have_z && (cur[0] == 'l' && cur[1] == 'l');
164 cur += have_ll * 2;
165 s64 dval;
166 u64 uval;
167 const bool have_length = have_z || have_ll;
168 const bool have_flags = have_width || have_length;
169 // At the moment only %s supports precision and left-justification.
170 CHECK(!((precision >= 0 || left_justified) && *cur != 's'));
171 switch (*cur) {
172 case 'd': {
173 dval = have_ll ? va_arg(args, s64)
174 : have_z ? va_arg(args, sptr)
175 : va_arg(args, int);
176 result += AppendSignedDecimal(&buff, buff_end, dval, width,
177 pad_with_zero);
178 break;
179 }
180 case 'u':
181 case 'x':
182 case 'X': {
183 uval = have_ll ? va_arg(args, u64)
184 : have_z ? va_arg(args, uptr)
185 : va_arg(args, unsigned);
186 bool uppercase = (*cur == 'X');
187 result += AppendUnsigned(&buff, buff_end, uval, (*cur == 'u') ? 10 : 16,
188 width, pad_with_zero, uppercase);
189 break;
190 }
191 case 'p': {
192 RAW_CHECK_MSG(!have_flags, kPrintfFormatsHelp);
193 result += AppendPointer(&buff, buff_end, va_arg(args, uptr));
194 break;
195 }
196 case 's': {
197 RAW_CHECK_MSG(!have_length, kPrintfFormatsHelp);
198 // Only left-justified width is supported.
199 CHECK(!have_width || left_justified);
200 result += AppendString(&buff, buff_end, left_justified ? -width : width,
201 precision, va_arg(args, char*));
202 break;
203 }
204 case 'c': {
205 RAW_CHECK_MSG(!have_flags, kPrintfFormatsHelp);
206 result += AppendChar(&buff, buff_end, va_arg(args, int));
207 break;
208 }
209 case '%' : {
210 RAW_CHECK_MSG(!have_flags, kPrintfFormatsHelp);
211 result += AppendChar(&buff, buff_end, '%');
212 break;
213 }
214 default: {
215 RAW_CHECK_MSG(false, kPrintfFormatsHelp);
216 }
217 }
218 }
219 RAW_CHECK(buff <= buff_end);
220 AppendChar(&buff, buff_end + 1, '\0');
221 return result;
222}
223
224static void (*PrintfAndReportCallback)(const char *);
225void SetPrintfAndReportCallback(void (*callback)(const char *)) {
226 PrintfAndReportCallback = callback;
227}
228
229// Can be overriden in frontend.
230#if SANITIZER_GO && defined(TSAN_EXTERNAL_HOOKS)
231// Implementation must be defined in frontend.
232extern "C" void __sanitizer_on_print(const char *str);
233#else
234SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_on_print, const char *str) {
235 (void)str;
236}
237#endif
238
239static void CallPrintfAndReportCallback(const char *str) {
240 __sanitizer_on_print(str);
241 if (PrintfAndReportCallback)
242 PrintfAndReportCallback(str);
243}
244
245static void NOINLINE SharedPrintfCodeNoBuffer(bool append_pid,
246 char *local_buffer,
247 int buffer_size,
248 const char *format,
249 va_list args) {
250 va_list args2;
251 va_copy(args2, args);
252 const int kLen = 16 * 1024;
253 int needed_length;
254 char *buffer = local_buffer;
255 // First try to print a message using a local buffer, and then fall back to
256 // mmaped buffer.
257 for (int use_mmap = 0; use_mmap < 2; use_mmap++) {
258 if (use_mmap) {
259 va_end(args);
260 va_copy(args, args2);
261 buffer = (char*)MmapOrDie(kLen, "Report");
262 buffer_size = kLen;
263 }
264 needed_length = 0;
265 // Check that data fits into the current buffer.
266# define CHECK_NEEDED_LENGTH \
267 if (needed_length >= buffer_size) { \
268 if (!use_mmap) continue; \
269 RAW_CHECK_MSG(needed_length < kLen, \
270 "Buffer in Report is too short!\n"); \
271 }
272 // Fuchsia's logging infrastructure always keeps track of the logging
273 // process, thread, and timestamp, so never prepend such information.
274 if (!SANITIZER_FUCHSIA && append_pid) {
275 int pid = internal_getpid();
276 const char *exe_name = GetProcessName();
277 if (common_flags()->log_exe_name && exe_name) {
278 needed_length += internal_snprintf(buffer, buffer_size,
279 "==%s", exe_name);
280 CHECK_NEEDED_LENGTH
281 }
282 needed_length += internal_snprintf(
283 buffer + needed_length, buffer_size - needed_length, "==%d==", pid);
284 CHECK_NEEDED_LENGTH
285 }
286 needed_length += VSNPrintf(buffer + needed_length,
287 buffer_size - needed_length, format, args);
288 CHECK_NEEDED_LENGTH
289 // If the message fit into the buffer, print it and exit.
290 break;
291# undef CHECK_NEEDED_LENGTH
292 }
293 RawWrite(buffer);
294
295 // Remove color sequences from the message.
296 RemoveANSIEscapeSequencesFromString(buffer);
297 CallPrintfAndReportCallback(buffer);
298 LogMessageOnPrintf(buffer);
299
300 // If we had mapped any memory, clean up.
301 if (buffer != local_buffer)
302 UnmapOrDie((void *)buffer, buffer_size);
303 va_end(args2);
304}
305
306static void NOINLINE SharedPrintfCode(bool append_pid, const char *format,
307 va_list args) {
308 // |local_buffer| is small enough not to overflow the stack and/or violate
309 // the stack limit enforced by TSan (-Wframe-larger-than=512). On the other
310 // hand, the bigger the buffer is, the more the chance the error report will
311 // fit into it.
312 char local_buffer[400];
313 SharedPrintfCodeNoBuffer(append_pid, local_buffer, ARRAY_SIZE(local_buffer),
314 format, args);
315}
316
317FORMAT(1, 2)
318void Printf(const char *format, ...) {
319 va_list args;
320 va_start(args, format);
321 SharedPrintfCode(false, format, args);
322 va_end(args);
323}
324
325// Like Printf, but prints the current PID before the output string.
326FORMAT(1, 2)
327void Report(const char *format, ...) {
328 va_list args;
329 va_start(args, format);
330 SharedPrintfCode(true, format, args);
331 va_end(args);
332}
333
334// Writes at most "length" symbols to "buffer" (including trailing '\0').
335// Returns the number of symbols that should have been written to buffer
336// (not including trailing '\0'). Thus, the string is truncated
337// iff return value is not less than "length".
338FORMAT(3, 4)
339int internal_snprintf(char *buffer, uptr length, const char *format, ...) {
340 va_list args;
341 va_start(args, format);
342 int needed_length = VSNPrintf(buffer, length, format, args);
343 va_end(args);
344 return needed_length;
345}
346
347FORMAT(2, 3)
348void InternalScopedString::append(const char *format, ...) {
349 CHECK_LT(length_, size());
350 va_list args;
351 va_start(args, format);
352 VSNPrintf(data() + length_, size() - length_, format, args);
353 va_end(args);
354 length_ += internal_strlen(data() + length_);
355 CHECK_LT(length_, size());
356}
357
358} // namespace __sanitizer
lib/tsan/sanitizer_common/sanitizer_procmaps.h created+100
...@@ -0,0 +1,100 @@
1//===-- sanitizer_procmaps.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 AddressSanitizer and ThreadSanitizer.
10//
11// Information about the process mappings.
12//===----------------------------------------------------------------------===//
13#ifndef SANITIZER_PROCMAPS_H
14#define SANITIZER_PROCMAPS_H
15
16#include "sanitizer_platform.h"
17
18#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \
19 SANITIZER_OPENBSD || SANITIZER_MAC || SANITIZER_SOLARIS || \
20 SANITIZER_FUCHSIA
21
22#include "sanitizer_common.h"
23#include "sanitizer_internal_defs.h"
24#include "sanitizer_fuchsia.h"
25#include "sanitizer_linux.h"
26#include "sanitizer_mac.h"
27#include "sanitizer_mutex.h"
28
29namespace __sanitizer {
30
31// Memory protection masks.
32static const uptr kProtectionRead = 1;
33static const uptr kProtectionWrite = 2;
34static const uptr kProtectionExecute = 4;
35static const uptr kProtectionShared = 8;
36
37struct MemoryMappedSegmentData;
38
39class MemoryMappedSegment {
40 public:
41 explicit MemoryMappedSegment(char *buff = nullptr, uptr size = 0)
42 : filename(buff), filename_size(size), data_(nullptr) {}
43 ~MemoryMappedSegment() {}
44
45 bool IsReadable() const { return protection & kProtectionRead; }
46 bool IsWritable() const { return protection & kProtectionWrite; }
47 bool IsExecutable() const { return protection & kProtectionExecute; }
48 bool IsShared() const { return protection & kProtectionShared; }
49
50 void AddAddressRanges(LoadedModule *module);
51
52 uptr start;
53 uptr end;
54 uptr offset;
55 char *filename; // owned by caller
56 uptr filename_size;
57 uptr protection;
58 ModuleArch arch;
59 u8 uuid[kModuleUUIDSize];
60
61 private:
62 friend class MemoryMappingLayout;
63
64 // This field is assigned and owned by MemoryMappingLayout if needed
65 MemoryMappedSegmentData *data_;
66};
67
68class MemoryMappingLayout {
69 public:
70 explicit MemoryMappingLayout(bool cache_enabled);
71 ~MemoryMappingLayout();
72 bool Next(MemoryMappedSegment *segment);
73 bool Error() const;
74 void Reset();
75 // In some cases, e.g. when running under a sandbox on Linux, ASan is unable
76 // to obtain the memory mappings. It should fall back to pre-cached data
77 // instead of aborting.
78 static void CacheMemoryMappings();
79
80 // Adds all mapped objects into a vector.
81 void DumpListOfModules(InternalMmapVectorNoCtor<LoadedModule> *modules);
82
83 private:
84 void LoadFromCache();
85
86 MemoryMappingLayoutData data_;
87};
88
89// Returns code range for the specified module.
90bool GetCodeRangeForFile(const char *module, uptr *start, uptr *end);
91
92bool IsDecimal(char c);
93uptr ParseDecimal(const char **p);
94bool IsHex(char c);
95uptr ParseHex(const char **p);
96
97} // namespace __sanitizer
98
99#endif
100#endif // SANITIZER_PROCMAPS_H
lib/tsan/sanitizer_common/sanitizer_procmaps_bsd.cpp created+139
...@@ -0,0 +1,139 @@
1//===-- sanitizer_procmaps_bsd.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// Information about the process mappings
10// (FreeBSD, OpenBSD and NetBSD-specific parts).
11//===----------------------------------------------------------------------===//
12
13#include "sanitizer_platform.h"
14#if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_OPENBSD
15#include "sanitizer_common.h"
16#if SANITIZER_FREEBSD
17#include "sanitizer_freebsd.h"
18#endif
19#include "sanitizer_procmaps.h"
20
21// clang-format off
22#include <sys/types.h>
23#include <sys/sysctl.h>
24// clang-format on
25#include <unistd.h>
26#if SANITIZER_FREEBSD
27#include <sys/user.h>
28#endif
29
30#include <limits.h>
31#if SANITIZER_OPENBSD
32#define KVME_PROT_READ KVE_PROT_READ
33#define KVME_PROT_WRITE KVE_PROT_WRITE
34#define KVME_PROT_EXEC KVE_PROT_EXEC
35#endif
36
37// Fix 'kinfo_vmentry' definition on FreeBSD prior v9.2 in 32-bit mode.
38#if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32)
39#include <osreldate.h>
40#if __FreeBSD_version <= 902001 // v9.2
41#define kinfo_vmentry xkinfo_vmentry
42#endif
43#endif
44
45namespace __sanitizer {
46
47void ReadProcMaps(ProcSelfMapsBuff *proc_maps) {
48 const int Mib[] = {
49#if SANITIZER_FREEBSD
50 CTL_KERN,
51 KERN_PROC,
52 KERN_PROC_VMMAP,
53 getpid()
54#elif SANITIZER_OPENBSD
55 CTL_KERN,
56 KERN_PROC_VMMAP,
57 getpid()
58#elif SANITIZER_NETBSD
59 CTL_VM,
60 VM_PROC,
61 VM_PROC_MAP,
62 getpid(),
63 sizeof(struct kinfo_vmentry)
64#else
65#error "not supported"
66#endif
67 };
68
69 uptr Size = 0;
70 int Err = internal_sysctl(Mib, ARRAY_SIZE(Mib), NULL, &Size, NULL, 0);
71 CHECK_EQ(Err, 0);
72 CHECK_GT(Size, 0);
73
74#if !SANITIZER_OPENBSD
75 size_t MmapedSize = Size * 4 / 3;
76 void *VmMap = MmapOrDie(MmapedSize, "ReadProcMaps()");
77 Size = MmapedSize;
78 Err = internal_sysctl(Mib, ARRAY_SIZE(Mib), VmMap, &Size, NULL, 0);
79 CHECK_EQ(Err, 0);
80 proc_maps->data = (char *)VmMap;
81#else
82 size_t PageSize = GetPageSize();
83 size_t MmapedSize = Size;
84 MmapedSize = ((MmapedSize - 1) / PageSize + 1) * PageSize;
85 char *Mem = (char *)MmapOrDie(MmapedSize, "ReadProcMaps()");
86 Size = 2 * Size + 10 * sizeof(struct kinfo_vmentry);
87 if (Size > 0x10000)
88 Size = 0x10000;
89 Size = (Size / sizeof(struct kinfo_vmentry)) * sizeof(struct kinfo_vmentry);
90 Err = internal_sysctl(Mib, ARRAY_SIZE(Mib), Mem, &Size, NULL, 0);
91 CHECK_EQ(Err, 0);
92 MmapedSize = Size;
93 proc_maps->data = Mem;
94#endif
95
96 proc_maps->mmaped_size = MmapedSize;
97 proc_maps->len = Size;
98}
99
100bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {
101 CHECK(!Error()); // can not fail
102 char *last = data_.proc_self_maps.data + data_.proc_self_maps.len;
103 if (data_.current >= last)
104 return false;
105 const struct kinfo_vmentry *VmEntry =
106 (const struct kinfo_vmentry *)data_.current;
107
108 segment->start = (uptr)VmEntry->kve_start;
109 segment->end = (uptr)VmEntry->kve_end;
110 segment->offset = (uptr)VmEntry->kve_offset;
111
112 segment->protection = 0;
113 if ((VmEntry->kve_protection & KVME_PROT_READ) != 0)
114 segment->protection |= kProtectionRead;
115 if ((VmEntry->kve_protection & KVME_PROT_WRITE) != 0)
116 segment->protection |= kProtectionWrite;
117 if ((VmEntry->kve_protection & KVME_PROT_EXEC) != 0)
118 segment->protection |= kProtectionExecute;
119
120#if !SANITIZER_OPENBSD
121 if (segment->filename != NULL && segment->filename_size > 0) {
122 internal_snprintf(segment->filename,
123 Min(segment->filename_size, (uptr)PATH_MAX), "%s",
124 VmEntry->kve_path);
125 }
126#endif
127
128#if SANITIZER_FREEBSD
129 data_.current += VmEntry->kve_structsize;
130#else
131 data_.current += sizeof(*VmEntry);
132#endif
133
134 return true;
135}
136
137} // namespace __sanitizer
138
139#endif
lib/tsan/sanitizer_common/sanitizer_procmaps_common.cpp created+174
...@@ -0,0 +1,174 @@
1//===-- sanitizer_procmaps_common.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// Information about the process mappings (common parts).
10//===----------------------------------------------------------------------===//
11
12#include "sanitizer_platform.h"
13
14#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
15 SANITIZER_OPENBSD || SANITIZER_SOLARIS
16
17#include "sanitizer_common.h"
18#include "sanitizer_placement_new.h"
19#include "sanitizer_procmaps.h"
20
21namespace __sanitizer {
22
23static ProcSelfMapsBuff cached_proc_self_maps;
24static StaticSpinMutex cache_lock;
25
26static int TranslateDigit(char c) {
27 if (c >= '0' && c <= '9')
28 return c - '0';
29 if (c >= 'a' && c <= 'f')
30 return c - 'a' + 10;
31 if (c >= 'A' && c <= 'F')
32 return c - 'A' + 10;
33 return -1;
34}
35
36// Parse a number and promote 'p' up to the first non-digit character.
37static uptr ParseNumber(const char **p, int base) {
38 uptr n = 0;
39 int d;
40 CHECK(base >= 2 && base <= 16);
41 while ((d = TranslateDigit(**p)) >= 0 && d < base) {
42 n = n * base + d;
43 (*p)++;
44 }
45 return n;
46}
47
48bool IsDecimal(char c) {
49 int d = TranslateDigit(c);
50 return d >= 0 && d < 10;
51}
52
53uptr ParseDecimal(const char **p) {
54 return ParseNumber(p, 10);
55}
56
57bool IsHex(char c) {
58 int d = TranslateDigit(c);
59 return d >= 0 && d < 16;
60}
61
62uptr ParseHex(const char **p) {
63 return ParseNumber(p, 16);
64}
65
66void MemoryMappedSegment::AddAddressRanges(LoadedModule *module) {
67 // data_ should be unused on this platform
68 CHECK(!data_);
69 module->addAddressRange(start, end, IsExecutable(), IsWritable());
70}
71
72MemoryMappingLayout::MemoryMappingLayout(bool cache_enabled) {
73 // FIXME: in the future we may want to cache the mappings on demand only.
74 if (cache_enabled)
75 CacheMemoryMappings();
76
77 // Read maps after the cache update to capture the maps/unmaps happening in
78 // the process of updating.
79 ReadProcMaps(&data_.proc_self_maps);
80 if (cache_enabled && data_.proc_self_maps.mmaped_size == 0)
81 LoadFromCache();
82
83 Reset();
84}
85
86bool MemoryMappingLayout::Error() const {
87 return data_.current == nullptr;
88}
89
90MemoryMappingLayout::~MemoryMappingLayout() {
91 // Only unmap the buffer if it is different from the cached one. Otherwise
92 // it will be unmapped when the cache is refreshed.
93 if (data_.proc_self_maps.data != cached_proc_self_maps.data)
94 UnmapOrDie(data_.proc_self_maps.data, data_.proc_self_maps.mmaped_size);
95}
96
97void MemoryMappingLayout::Reset() {
98 data_.current = data_.proc_self_maps.data;
99}
100
101// static
102void MemoryMappingLayout::CacheMemoryMappings() {
103 ProcSelfMapsBuff new_proc_self_maps;
104 ReadProcMaps(&new_proc_self_maps);
105 // Don't invalidate the cache if the mappings are unavailable.
106 if (new_proc_self_maps.mmaped_size == 0)
107 return;
108 SpinMutexLock l(&cache_lock);
109 if (cached_proc_self_maps.mmaped_size)
110 UnmapOrDie(cached_proc_self_maps.data, cached_proc_self_maps.mmaped_size);
111 cached_proc_self_maps = new_proc_self_maps;
112}
113
114void MemoryMappingLayout::LoadFromCache() {
115 SpinMutexLock l(&cache_lock);
116 if (cached_proc_self_maps.data)
117 data_.proc_self_maps = cached_proc_self_maps;
118}
119
120void MemoryMappingLayout::DumpListOfModules(
121 InternalMmapVectorNoCtor<LoadedModule> *modules) {
122 Reset();
123 InternalScopedString module_name(kMaxPathLength);
124 MemoryMappedSegment segment(module_name.data(), module_name.size());
125 for (uptr i = 0; Next(&segment); i++) {
126 const char *cur_name = segment.filename;
127 if (cur_name[0] == '\0')
128 continue;
129 // Don't subtract 'cur_beg' from the first entry:
130 // * If a binary is compiled w/o -pie, then the first entry in
131 // process maps is likely the binary itself (all dynamic libs
132 // are mapped higher in address space). For such a binary,
133 // instruction offset in binary coincides with the actual
134 // instruction address in virtual memory (as code section
135 // is mapped to a fixed memory range).
136 // * If a binary is compiled with -pie, all the modules are
137 // mapped high at address space (in particular, higher than
138 // shadow memory of the tool), so the module can't be the
139 // first entry.
140 uptr base_address = (i ? segment.start : 0) - segment.offset;
141 LoadedModule cur_module;
142 cur_module.set(cur_name, base_address);
143 segment.AddAddressRanges(&cur_module);
144 modules->push_back(cur_module);
145 }
146}
147
148void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size) {
149 char *smaps = nullptr;
150 uptr smaps_cap = 0;
151 uptr smaps_len = 0;
152 if (!ReadFileToBuffer("/proc/self/smaps", &smaps, &smaps_cap, &smaps_len))
153 return;
154 uptr start = 0;
155 bool file = false;
156 const char *pos = smaps;
157 while (pos < smaps + smaps_len) {
158 if (IsHex(pos[0])) {
159 start = ParseHex(&pos);
160 for (; *pos != '/' && *pos > '\n'; pos++) {}
161 file = *pos == '/';
162 } else if (internal_strncmp(pos, "Rss:", 4) == 0) {
163 while (!IsDecimal(*pos)) pos++;
164 uptr rss = ParseDecimal(&pos) * 1024;
165 cb(start, rss, file, stats, stats_size);
166 }
167 while (*pos++ != '\n') {}
168 }
169 UnmapOrDie(smaps, smaps_cap);
170}
171
172} // namespace __sanitizer
173
174#endif
lib/tsan/sanitizer_common/sanitizer_procmaps_fuchsia.cpp created+80
...@@ -0,0 +1,80 @@
1//===-- sanitizer_procmaps_fuchsia.cpp
2//----------------------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9//
10// Information about the process mappings (Fuchsia-specific parts).
11//===----------------------------------------------------------------------===//
12
13#include "sanitizer_platform.h"
14#if SANITIZER_FUCHSIA
15#include <zircon/process.h>
16#include <zircon/syscalls.h>
17
18#include "sanitizer_common.h"
19#include "sanitizer_procmaps.h"
20
21namespace __sanitizer {
22
23// The cache flag is ignored on Fuchsia because a process can always get this
24// information via its process-self handle.
25MemoryMappingLayout::MemoryMappingLayout(bool) { Reset(); }
26
27void MemoryMappingLayout::Reset() {
28 data_.data.clear();
29 data_.current = 0;
30
31 size_t count;
32 zx_status_t status = _zx_object_get_info(
33 _zx_process_self(), ZX_INFO_PROCESS_MAPS, nullptr, 0, nullptr, &count);
34 if (status != ZX_OK) {
35 return;
36 }
37
38 size_t filled;
39 do {
40 data_.data.resize(count);
41 status = _zx_object_get_info(
42 _zx_process_self(), ZX_INFO_PROCESS_MAPS, data_.data.data(),
43 count * sizeof(zx_info_maps_t), &filled, &count);
44 if (status != ZX_OK) {
45 data_.data.clear();
46 return;
47 }
48 } while (filled < count);
49}
50
51MemoryMappingLayout::~MemoryMappingLayout() {}
52
53bool MemoryMappingLayout::Error() const { return data_.data.empty(); }
54
55bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {
56 while (data_.current < data_.data.size()) {
57 const auto &entry = data_.data[data_.current++];
58 if (entry.type == ZX_INFO_MAPS_TYPE_MAPPING) {
59 segment->start = entry.base;
60 segment->end = entry.base + entry.size;
61 segment->offset = entry.u.mapping.vmo_offset;
62 const auto flags = entry.u.mapping.mmu_flags;
63 segment->protection =
64 ((flags & ZX_VM_PERM_READ) ? kProtectionRead : 0) |
65 ((flags & ZX_VM_PERM_WRITE) ? kProtectionWrite : 0) |
66 ((flags & ZX_VM_PERM_EXECUTE) ? kProtectionExecute : 0);
67 if (segment->filename && segment->filename_size > 0) {
68 uptr len = Min(sizeof(entry.name), segment->filename_size) - 1;
69 internal_strncpy(segment->filename, entry.name, len);
70 segment->filename[len] = 0;
71 }
72 return true;
73 }
74 }
75 return false;
76}
77
78} // namespace __sanitizer
79
80#endif // SANITIZER_FUCHSIA
lib/tsan/sanitizer_common/sanitizer_procmaps_linux.cpp created+81
...@@ -0,0 +1,81 @@
1//===-- sanitizer_procmaps_linux.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// Information about the process mappings (Linux-specific parts).
10//===----------------------------------------------------------------------===//
11
12#include "sanitizer_platform.h"
13#if SANITIZER_LINUX
14#include "sanitizer_common.h"
15#include "sanitizer_procmaps.h"
16
17namespace __sanitizer {
18
19void ReadProcMaps(ProcSelfMapsBuff *proc_maps) {
20 if (!ReadFileToBuffer("/proc/self/maps", &proc_maps->data,
21 &proc_maps->mmaped_size, &proc_maps->len)) {
22 proc_maps->data = nullptr;
23 proc_maps->mmaped_size = 0;
24 proc_maps->len = 0;
25 }
26}
27
28static bool IsOneOf(char c, char c1, char c2) {
29 return c == c1 || c == c2;
30}
31
32bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {
33 if (Error()) return false; // simulate empty maps
34 char *last = data_.proc_self_maps.data + data_.proc_self_maps.len;
35 if (data_.current >= last) return false;
36 char *next_line =
37 (char *)internal_memchr(data_.current, '\n', last - data_.current);
38 if (next_line == 0)
39 next_line = last;
40 // Example: 08048000-08056000 r-xp 00000000 03:0c 64593 /foo/bar
41 segment->start = ParseHex(&data_.current);
42 CHECK_EQ(*data_.current++, '-');
43 segment->end = ParseHex(&data_.current);
44 CHECK_EQ(*data_.current++, ' ');
45 CHECK(IsOneOf(*data_.current, '-', 'r'));
46 segment->protection = 0;
47 if (*data_.current++ == 'r') segment->protection |= kProtectionRead;
48 CHECK(IsOneOf(*data_.current, '-', 'w'));
49 if (*data_.current++ == 'w') segment->protection |= kProtectionWrite;
50 CHECK(IsOneOf(*data_.current, '-', 'x'));
51 if (*data_.current++ == 'x') segment->protection |= kProtectionExecute;
52 CHECK(IsOneOf(*data_.current, 's', 'p'));
53 if (*data_.current++ == 's') segment->protection |= kProtectionShared;
54 CHECK_EQ(*data_.current++, ' ');
55 segment->offset = ParseHex(&data_.current);
56 CHECK_EQ(*data_.current++, ' ');
57 ParseHex(&data_.current);
58 CHECK_EQ(*data_.current++, ':');
59 ParseHex(&data_.current);
60 CHECK_EQ(*data_.current++, ' ');
61 while (IsDecimal(*data_.current)) data_.current++;
62 // Qemu may lack the trailing space.
63 // https://github.com/google/sanitizers/issues/160
64 // CHECK_EQ(*data_.current++, ' ');
65 // Skip spaces.
66 while (data_.current < next_line && *data_.current == ' ') data_.current++;
67 // Fill in the filename.
68 if (segment->filename) {
69 uptr len =
70 Min((uptr)(next_line - data_.current), segment->filename_size - 1);
71 internal_strncpy(segment->filename, data_.current, len);
72 segment->filename[len] = 0;
73 }
74
75 data_.current = next_line + 1;
76 return true;
77}
78
79} // namespace __sanitizer
80
81#endif // SANITIZER_LINUX
lib/tsan/sanitizer_common/sanitizer_procmaps_mac.cpp created+379
...@@ -0,0 +1,379 @@
1//===-- sanitizer_procmaps_mac.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// Information about the process mappings (Mac-specific parts).
10//===----------------------------------------------------------------------===//
11
12#include "sanitizer_platform.h"
13#if SANITIZER_MAC
14#include "sanitizer_common.h"
15#include "sanitizer_placement_new.h"
16#include "sanitizer_procmaps.h"
17
18#include <mach-o/dyld.h>
19#include <mach-o/loader.h>
20#include <mach/mach.h>
21
22// These are not available in older macOS SDKs.
23#ifndef CPU_SUBTYPE_X86_64_H
24#define CPU_SUBTYPE_X86_64_H ((cpu_subtype_t)8) /* Haswell */
25#endif
26#ifndef CPU_SUBTYPE_ARM_V7S
27#define CPU_SUBTYPE_ARM_V7S ((cpu_subtype_t)11) /* Swift */
28#endif
29#ifndef CPU_SUBTYPE_ARM_V7K
30#define CPU_SUBTYPE_ARM_V7K ((cpu_subtype_t)12)
31#endif
32#ifndef CPU_TYPE_ARM64
33#define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64)
34#endif
35
36namespace __sanitizer {
37
38// Contains information used to iterate through sections.
39struct MemoryMappedSegmentData {
40 char name[kMaxSegName];
41 uptr nsects;
42 const char *current_load_cmd_addr;
43 u32 lc_type;
44 uptr base_virt_addr;
45 uptr addr_mask;
46};
47
48template <typename Section>
49static void NextSectionLoad(LoadedModule *module, MemoryMappedSegmentData *data,
50 bool isWritable) {
51 const Section *sc = (const Section *)data->current_load_cmd_addr;
52 data->current_load_cmd_addr += sizeof(Section);
53
54 uptr sec_start = (sc->addr & data->addr_mask) + data->base_virt_addr;
55 uptr sec_end = sec_start + sc->size;
56 module->addAddressRange(sec_start, sec_end, /*executable=*/false, isWritable,
57 sc->sectname);
58}
59
60void MemoryMappedSegment::AddAddressRanges(LoadedModule *module) {
61 // Don't iterate over sections when the caller hasn't set up the
62 // data pointer, when there are no sections, or when the segment
63 // is executable. Avoid iterating over executable sections because
64 // it will confuse libignore, and because the extra granularity
65 // of information is not needed by any sanitizers.
66 if (!data_ || !data_->nsects || IsExecutable()) {
67 module->addAddressRange(start, end, IsExecutable(), IsWritable(),
68 data_ ? data_->name : nullptr);
69 return;
70 }
71
72 do {
73 if (data_->lc_type == LC_SEGMENT) {
74 NextSectionLoad<struct section>(module, data_, IsWritable());
75#ifdef MH_MAGIC_64
76 } else if (data_->lc_type == LC_SEGMENT_64) {
77 NextSectionLoad<struct section_64>(module, data_, IsWritable());
78#endif
79 }
80 } while (--data_->nsects);
81}
82
83MemoryMappingLayout::MemoryMappingLayout(bool cache_enabled) {
84 Reset();
85}
86
87MemoryMappingLayout::~MemoryMappingLayout() {
88}
89
90bool MemoryMappingLayout::Error() const {
91 return false;
92}
93
94// More information about Mach-O headers can be found in mach-o/loader.h
95// Each Mach-O image has a header (mach_header or mach_header_64) starting with
96// a magic number, and a list of linker load commands directly following the
97// header.
98// A load command is at least two 32-bit words: the command type and the
99// command size in bytes. We're interested only in segment load commands
100// (LC_SEGMENT and LC_SEGMENT_64), which tell that a part of the file is mapped
101// into the task's address space.
102// The |vmaddr|, |vmsize| and |fileoff| fields of segment_command or
103// segment_command_64 correspond to the memory address, memory size and the
104// file offset of the current memory segment.
105// Because these fields are taken from the images as is, one needs to add
106// _dyld_get_image_vmaddr_slide() to get the actual addresses at runtime.
107
108void MemoryMappingLayout::Reset() {
109 // Count down from the top.
110 // TODO(glider): as per man 3 dyld, iterating over the headers with
111 // _dyld_image_count is thread-unsafe. We need to register callbacks for
112 // adding and removing images which will invalidate the MemoryMappingLayout
113 // state.
114 data_.current_image = _dyld_image_count();
115 data_.current_load_cmd_count = -1;
116 data_.current_load_cmd_addr = 0;
117 data_.current_magic = 0;
118 data_.current_filetype = 0;
119 data_.current_arch = kModuleArchUnknown;
120 internal_memset(data_.current_uuid, 0, kModuleUUIDSize);
121}
122
123// The dyld load address should be unchanged throughout process execution,
124// and it is expensive to compute once many libraries have been loaded,
125// so cache it here and do not reset.
126static mach_header *dyld_hdr = 0;
127static const char kDyldPath[] = "/usr/lib/dyld";
128static const int kDyldImageIdx = -1;
129
130// static
131void MemoryMappingLayout::CacheMemoryMappings() {
132 // No-op on Mac for now.
133}
134
135void MemoryMappingLayout::LoadFromCache() {
136 // No-op on Mac for now.
137}
138
139// _dyld_get_image_header() and related APIs don't report dyld itself.
140// We work around this by manually recursing through the memory map
141// until we hit a Mach header matching dyld instead. These recurse
142// calls are expensive, but the first memory map generation occurs
143// 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;
148 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;
151
152 while (true) {
153 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);
156 if (err != KERN_SUCCESS) return nullptr;
157
158 if (size >= sizeof(mach_header) && info.protection & kProtectionRead) {
159 mach_header *hdr = (mach_header *)address;
160 if ((hdr->magic == MH_MAGIC || hdr->magic == MH_MAGIC_64) &&
161 hdr->filetype == MH_DYLINKER) {
162 return hdr;
163 }
164 }
165 address += size;
166 }
167}
168
169const mach_header *get_dyld_hdr() {
170 if (!dyld_hdr) dyld_hdr = get_dyld_image_header();
171
172 return dyld_hdr;
173}
174
175// Next and NextSegmentLoad were inspired by base/sysinfo.cc in
176// Google Perftools, https://github.com/gperftools/gperftools.
177
178// NextSegmentLoad scans the current image for the next segment load command
179// and returns the start and end addresses and file offset of the corresponding
180// segment.
181// Note that the segment addresses are not necessarily sorted.
182template <u32 kLCSegment, typename SegmentCommand>
183static bool NextSegmentLoad(MemoryMappedSegment *segment,
184 MemoryMappedSegmentData *seg_data,
185 MemoryMappingLayoutData *layout_data) {
186 const char *lc = layout_data->current_load_cmd_addr;
187 layout_data->current_load_cmd_addr += ((const load_command *)lc)->cmdsize;
188 if (((const load_command *)lc)->cmd == kLCSegment) {
189 const SegmentCommand* sc = (const SegmentCommand *)lc;
190 uptr base_virt_addr, addr_mask;
191 if (layout_data->current_image == kDyldImageIdx) {
192 base_virt_addr = (uptr)get_dyld_hdr();
193 // vmaddr is masked with 0xfffff because on macOS versions < 10.12,
194 // it contains an absolute address rather than an offset for dyld.
195 // To make matters even more complicated, this absolute address
196 // isn't actually the absolute segment address, but the offset portion
197 // of the address is accurate when combined with the dyld base address,
198 // and the mask will give just this offset.
199 addr_mask = 0xfffff;
200 } else {
201 base_virt_addr =
202 (uptr)_dyld_get_image_vmaddr_slide(layout_data->current_image);
203 addr_mask = ~0;
204 }
205
206 segment->start = (sc->vmaddr & addr_mask) + base_virt_addr;
207 segment->end = segment->start + sc->vmsize;
208 // Most callers don't need section information, so only fill this struct
209 // when required.
210 if (seg_data) {
211 seg_data->nsects = sc->nsects;
212 seg_data->current_load_cmd_addr =
213 (const char *)lc + sizeof(SegmentCommand);
214 seg_data->lc_type = kLCSegment;
215 seg_data->base_virt_addr = base_virt_addr;
216 seg_data->addr_mask = addr_mask;
217 internal_strncpy(seg_data->name, sc->segname,
218 ARRAY_SIZE(seg_data->name));
219 }
220
221 // Return the initial protection.
222 segment->protection = sc->initprot;
223 segment->offset = (layout_data->current_filetype ==
224 /*MH_EXECUTE*/ 0x2)
225 ? sc->vmaddr
226 : sc->fileoff;
227 if (segment->filename) {
228 const char *src = (layout_data->current_image == kDyldImageIdx)
229 ? kDyldPath
230 : _dyld_get_image_name(layout_data->current_image);
231 internal_strncpy(segment->filename, src, segment->filename_size);
232 }
233 segment->arch = layout_data->current_arch;
234 internal_memcpy(segment->uuid, layout_data->current_uuid, kModuleUUIDSize);
235 return true;
236 }
237 return false;
238}
239
240ModuleArch ModuleArchFromCpuType(cpu_type_t cputype, cpu_subtype_t cpusubtype) {
241 cpusubtype = cpusubtype & ~CPU_SUBTYPE_MASK;
242 switch (cputype) {
243 case CPU_TYPE_I386:
244 return kModuleArchI386;
245 case CPU_TYPE_X86_64:
246 if (cpusubtype == CPU_SUBTYPE_X86_64_ALL) return kModuleArchX86_64;
247 if (cpusubtype == CPU_SUBTYPE_X86_64_H) return kModuleArchX86_64H;
248 CHECK(0 && "Invalid subtype of x86_64");
249 return kModuleArchUnknown;
250 case CPU_TYPE_ARM:
251 if (cpusubtype == CPU_SUBTYPE_ARM_V6) return kModuleArchARMV6;
252 if (cpusubtype == CPU_SUBTYPE_ARM_V7) return kModuleArchARMV7;
253 if (cpusubtype == CPU_SUBTYPE_ARM_V7S) return kModuleArchARMV7S;
254 if (cpusubtype == CPU_SUBTYPE_ARM_V7K) return kModuleArchARMV7K;
255 CHECK(0 && "Invalid subtype of ARM");
256 return kModuleArchUnknown;
257 case CPU_TYPE_ARM64:
258 return kModuleArchARM64;
259 default:
260 CHECK(0 && "Invalid CPU type");
261 return kModuleArchUnknown;
262 }
263}
264
265static const load_command *NextCommand(const load_command *lc) {
266 return (const load_command *)((const char *)lc + lc->cmdsize);
267}
268
269static void FindUUID(const load_command *first_lc, u8 *uuid_output) {
270 for (const load_command *lc = first_lc; lc->cmd != 0; lc = NextCommand(lc)) {
271 if (lc->cmd != LC_UUID) continue;
272
273 const uuid_command *uuid_lc = (const uuid_command *)lc;
274 const uint8_t *uuid = &uuid_lc->uuid[0];
275 internal_memcpy(uuid_output, uuid, kModuleUUIDSize);
276 return;
277 }
278}
279
280static bool IsModuleInstrumented(const load_command *first_lc) {
281 for (const load_command *lc = first_lc; lc->cmd != 0; lc = NextCommand(lc)) {
282 if (lc->cmd != LC_LOAD_DYLIB) continue;
283
284 const dylib_command *dylib_lc = (const dylib_command *)lc;
285 uint32_t dylib_name_offset = dylib_lc->dylib.name.offset;
286 const char *dylib_name = ((const char *)dylib_lc) + dylib_name_offset;
287 dylib_name = StripModuleName(dylib_name);
288 if (dylib_name != 0 && (internal_strstr(dylib_name, "libclang_rt."))) {
289 return true;
290 }
291 }
292 return false;
293}
294
295bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {
296 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);
300 if (!hdr) continue;
301 if (data_.current_load_cmd_count < 0) {
302 // Set up for this image;
303 data_.current_load_cmd_count = hdr->ncmds;
304 data_.current_magic = hdr->magic;
305 data_.current_filetype = hdr->filetype;
306 data_.current_arch = ModuleArchFromCpuType(hdr->cputype, hdr->cpusubtype);
307 switch (data_.current_magic) {
308#ifdef MH_MAGIC_64
309 case MH_MAGIC_64: {
310 data_.current_load_cmd_addr =
311 (const char *)hdr + sizeof(mach_header_64);
312 break;
313 }
314#endif
315 case MH_MAGIC: {
316 data_.current_load_cmd_addr = (const char *)hdr + sizeof(mach_header);
317 break;
318 }
319 default: {
320 continue;
321 }
322 }
323 FindUUID((const load_command *)data_.current_load_cmd_addr,
324 data_.current_uuid);
325 data_.current_instrumented = IsModuleInstrumented(
326 (const load_command *)data_.current_load_cmd_addr);
327 }
328
329 for (; data_.current_load_cmd_count >= 0; data_.current_load_cmd_count--) {
330 switch (data_.current_magic) {
331 // data_.current_magic may be only one of MH_MAGIC, MH_MAGIC_64.
332#ifdef MH_MAGIC_64
333 case MH_MAGIC_64: {
334 if (NextSegmentLoad<LC_SEGMENT_64, struct segment_command_64>(
335 segment, segment->data_, &data_))
336 return true;
337 break;
338 }
339#endif
340 case MH_MAGIC: {
341 if (NextSegmentLoad<LC_SEGMENT, struct segment_command>(
342 segment, segment->data_, &data_))
343 return true;
344 break;
345 }
346 }
347 }
348 // If we get here, no more load_cmd's in this image talk about
349 // segments. Go on to the next image.
350 }
351 return false;
352}
353
354void MemoryMappingLayout::DumpListOfModules(
355 InternalMmapVectorNoCtor<LoadedModule> *modules) {
356 Reset();
357 InternalScopedString module_name(kMaxPathLength);
358 MemoryMappedSegment segment(module_name.data(), kMaxPathLength);
359 MemoryMappedSegmentData data;
360 segment.data_ = &data;
361 while (Next(&segment)) {
362 if (segment.filename[0] == '\0') continue;
363 LoadedModule *cur_module = nullptr;
364 if (!modules->empty() &&
365 0 == internal_strcmp(segment.filename, modules->back().full_name())) {
366 cur_module = &modules->back();
367 } else {
368 modules->push_back(LoadedModule());
369 cur_module = &modules->back();
370 cur_module->set(segment.filename, segment.start, segment.arch,
371 segment.uuid, data_.current_instrumented);
372 }
373 segment.AddAddressRanges(cur_module);
374 }
375}
376
377} // namespace __sanitizer
378
379#endif // SANITIZER_MAC
lib/tsan/sanitizer_common/sanitizer_procmaps_solaris.cpp created+67
...@@ -0,0 +1,67 @@
1//===-- sanitizer_procmaps_solaris.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// Information about the process mappings (Solaris-specific parts).
10//===----------------------------------------------------------------------===//
11
12#include "sanitizer_platform.h"
13#if SANITIZER_SOLARIS
14#include "sanitizer_common.h"
15#include "sanitizer_procmaps.h"
16
17// Before Solaris 11.4, <procfs.h> doesn't work in a largefile environment.
18#undef _FILE_OFFSET_BITS
19#include <procfs.h>
20#include <limits.h>
21
22namespace __sanitizer {
23
24void 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 }
31}
32
33bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {
34 if (Error()) return false; // simulate empty maps
35 char *last = data_.proc_self_maps.data + data_.proc_self_maps.len;
36 if (data_.current >= last) return false;
37
38 prxmap_t *xmapentry = (prxmap_t*)data_.current;
39
40 segment->start = (uptr)xmapentry->pr_vaddr;
41 segment->end = (uptr)(xmapentry->pr_vaddr + xmapentry->pr_size);
42 segment->offset = (uptr)xmapentry->pr_offset;
43
44 segment->protection = 0;
45 if ((xmapentry->pr_mflags & MA_READ) != 0)
46 segment->protection |= kProtectionRead;
47 if ((xmapentry->pr_mflags & MA_WRITE) != 0)
48 segment->protection |= kProtectionWrite;
49 if ((xmapentry->pr_mflags & MA_EXEC) != 0)
50 segment->protection |= kProtectionExecute;
51
52 if (segment->filename != NULL && segment->filename_size > 0) {
53 char proc_path[PATH_MAX + 1];
54
55 internal_snprintf(proc_path, sizeof(proc_path), "/proc/self/path/%s",
56 xmapentry->pr_mapname);
57 internal_readlink(proc_path, segment->filename, segment->filename_size);
58 }
59
60 data_.current += sizeof(prxmap_t);
61
62 return true;
63}
64
65} // namespace __sanitizer
66
67#endif // SANITIZER_SOLARIS
lib/tsan/sanitizer_common/sanitizer_ptrauth.h created+21
...@@ -0,0 +1,21 @@
1//===-- sanitizer_ptrauth.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_PTRAUTH_H
10#define SANITIZER_PTRAUTH_H
11
12#if __has_feature(ptrauth_calls)
13#include <ptrauth.h>
14#else
15// Copied from <ptrauth.h>
16#define ptrauth_strip(__value, __key) __value
17#define ptrauth_auth_data(__value, __old_key, __old_data) __value
18#define ptrauth_string_discriminator(__string) ((int)0)
19#endif
20
21#endif // SANITIZER_PTRAUTH_H
lib/tsan/sanitizer_common/sanitizer_quarantine.h created+317
...@@ -0,0 +1,317 @@
1//===-- sanitizer_quarantine.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// Memory quarantine for AddressSanitizer and potentially other tools.
10// Quarantine caches some specified amount of memory in per-thread caches,
11// then evicts to global FIFO queue. When the queue reaches specified threshold,
12// oldest memory is recycled.
13//
14//===----------------------------------------------------------------------===//
15
16#ifndef SANITIZER_QUARANTINE_H
17#define SANITIZER_QUARANTINE_H
18
19#include "sanitizer_internal_defs.h"
20#include "sanitizer_mutex.h"
21#include "sanitizer_list.h"
22
23namespace __sanitizer {
24
25template<typename Node> class QuarantineCache;
26
27struct QuarantineBatch {
28 static const uptr kSize = 1021;
29 QuarantineBatch *next;
30 uptr size;
31 uptr count;
32 void *batch[kSize];
33
34 void init(void *ptr, uptr size) {
35 count = 1;
36 batch[0] = ptr;
37 this->size = size + sizeof(QuarantineBatch); // Account for the batch size.
38 }
39
40 // The total size of quarantined nodes recorded in this batch.
41 uptr quarantined_size() const {
42 return size - sizeof(QuarantineBatch);
43 }
44
45 void push_back(void *ptr, uptr size) {
46 CHECK_LT(count, kSize);
47 batch[count++] = ptr;
48 this->size += size;
49 }
50
51 bool can_merge(const QuarantineBatch* const from) const {
52 return count + from->count <= kSize;
53 }
54
55 void merge(QuarantineBatch* const from) {
56 CHECK_LE(count + from->count, kSize);
57 CHECK_GE(size, sizeof(QuarantineBatch));
58
59 for (uptr i = 0; i < from->count; ++i)
60 batch[count + i] = from->batch[i];
61 count += from->count;
62 size += from->quarantined_size();
63
64 from->count = 0;
65 from->size = sizeof(QuarantineBatch);
66 }
67};
68
69COMPILER_CHECK(sizeof(QuarantineBatch) <= (1 << 13)); // 8Kb.
70
71// The callback interface is:
72// void Callback::Recycle(Node *ptr);
73// void *cb.Allocate(uptr size);
74// void cb.Deallocate(void *ptr);
75template<typename Callback, typename Node>
76class Quarantine {
77 public:
78 typedef QuarantineCache<Callback> Cache;
79
80 explicit Quarantine(LinkerInitialized)
81 : cache_(LINKER_INITIALIZED) {
82 }
83
84 void Init(uptr size, uptr cache_size) {
85 // Thread local quarantine size can be zero only when global quarantine size
86 // is zero (it allows us to perform just one atomic read per Put() call).
87 CHECK((size == 0 && cache_size == 0) || cache_size != 0);
88
89 atomic_store_relaxed(&max_size_, size);
90 atomic_store_relaxed(&min_size_, size / 10 * 9); // 90% of max size.
91 atomic_store_relaxed(&max_cache_size_, cache_size);
92
93 cache_mutex_.Init();
94 recycle_mutex_.Init();
95 }
96
97 uptr GetSize() const { return atomic_load_relaxed(&max_size_); }
98 uptr GetCacheSize() const {
99 return atomic_load_relaxed(&max_cache_size_);
100 }
101
102 void Put(Cache *c, Callback cb, Node *ptr, uptr size) {
103 uptr cache_size = GetCacheSize();
104 if (cache_size) {
105 c->Enqueue(cb, ptr, size);
106 } else {
107 // GetCacheSize() == 0 only when GetSize() == 0 (see Init).
108 cb.Recycle(ptr);
109 }
110 // Check cache size anyway to accommodate for runtime cache_size change.
111 if (c->Size() > cache_size)
112 Drain(c, cb);
113 }
114
115 void NOINLINE Drain(Cache *c, Callback cb) {
116 {
117 SpinMutexLock l(&cache_mutex_);
118 cache_.Transfer(c);
119 }
120 if (cache_.Size() > GetSize() && recycle_mutex_.TryLock())
121 Recycle(atomic_load_relaxed(&min_size_), cb);
122 }
123
124 void NOINLINE DrainAndRecycle(Cache *c, Callback cb) {
125 {
126 SpinMutexLock l(&cache_mutex_);
127 cache_.Transfer(c);
128 }
129 recycle_mutex_.Lock();
130 Recycle(0, cb);
131 }
132
133 void PrintStats() const {
134 // It assumes that the world is stopped, just as the allocator's PrintStats.
135 Printf("Quarantine limits: global: %zdMb; thread local: %zdKb\n",
136 GetSize() >> 20, GetCacheSize() >> 10);
137 cache_.PrintStats();
138 }
139
140 private:
141 // Read-only data.
142 char pad0_[kCacheLineSize];
143 atomic_uintptr_t max_size_;
144 atomic_uintptr_t min_size_;
145 atomic_uintptr_t max_cache_size_;
146 char pad1_[kCacheLineSize];
147 StaticSpinMutex cache_mutex_;
148 StaticSpinMutex recycle_mutex_;
149 Cache cache_;
150 char pad2_[kCacheLineSize];
151
152 void NOINLINE Recycle(uptr min_size, Callback cb) {
153 Cache tmp;
154 {
155 SpinMutexLock l(&cache_mutex_);
156 // Go over the batches and merge partially filled ones to
157 // save some memory, otherwise batches themselves (since the memory used
158 // by them is counted against quarantine limit) can overcome the actual
159 // user's quarantined chunks, which diminishes the purpose of the
160 // quarantine.
161 uptr cache_size = cache_.Size();
162 uptr overhead_size = cache_.OverheadSize();
163 CHECK_GE(cache_size, overhead_size);
164 // Do the merge only when overhead exceeds this predefined limit (might
165 // require some tuning). It saves us merge attempt when the batch list
166 // quarantine is unlikely to contain batches suitable for merge.
167 const uptr kOverheadThresholdPercents = 100;
168 if (cache_size > overhead_size &&
169 overhead_size * (100 + kOverheadThresholdPercents) >
170 cache_size * kOverheadThresholdPercents) {
171 cache_.MergeBatches(&tmp);
172 }
173 // Extract enough chunks from the quarantine to get below the max
174 // quarantine size and leave some leeway for the newly quarantined chunks.
175 while (cache_.Size() > min_size) {
176 tmp.EnqueueBatch(cache_.DequeueBatch());
177 }
178 }
179 recycle_mutex_.Unlock();
180 DoRecycle(&tmp, cb);
181 }
182
183 void NOINLINE DoRecycle(Cache *c, Callback cb) {
184 while (QuarantineBatch *b = c->DequeueBatch()) {
185 const uptr kPrefetch = 16;
186 CHECK(kPrefetch <= ARRAY_SIZE(b->batch));
187 for (uptr i = 0; i < kPrefetch; i++)
188 PREFETCH(b->batch[i]);
189 for (uptr i = 0, count = b->count; i < count; i++) {
190 if (i + kPrefetch < count)
191 PREFETCH(b->batch[i + kPrefetch]);
192 cb.Recycle((Node*)b->batch[i]);
193 }
194 cb.Deallocate(b);
195 }
196 }
197};
198
199// Per-thread cache of memory blocks.
200template<typename Callback>
201class QuarantineCache {
202 public:
203 explicit QuarantineCache(LinkerInitialized) {
204 }
205
206 QuarantineCache()
207 : size_() {
208 list_.clear();
209 }
210
211 // Total memory used, including internal accounting.
212 uptr Size() const {
213 return atomic_load_relaxed(&size_);
214 }
215
216 // Memory used for internal accounting.
217 uptr OverheadSize() const {
218 return list_.size() * sizeof(QuarantineBatch);
219 }
220
221 void Enqueue(Callback cb, void *ptr, uptr size) {
222 if (list_.empty() || list_.back()->count == QuarantineBatch::kSize) {
223 QuarantineBatch *b = (QuarantineBatch *)cb.Allocate(sizeof(*b));
224 CHECK(b);
225 b->init(ptr, size);
226 EnqueueBatch(b);
227 } else {
228 list_.back()->push_back(ptr, size);
229 SizeAdd(size);
230 }
231 }
232
233 void Transfer(QuarantineCache *from_cache) {
234 list_.append_back(&from_cache->list_);
235 SizeAdd(from_cache->Size());
236
237 atomic_store_relaxed(&from_cache->size_, 0);
238 }
239
240 void EnqueueBatch(QuarantineBatch *b) {
241 list_.push_back(b);
242 SizeAdd(b->size);
243 }
244
245 QuarantineBatch *DequeueBatch() {
246 if (list_.empty())
247 return nullptr;
248 QuarantineBatch *b = list_.front();
249 list_.pop_front();
250 SizeSub(b->size);
251 return b;
252 }
253
254 void MergeBatches(QuarantineCache *to_deallocate) {
255 uptr extracted_size = 0;
256 QuarantineBatch *current = list_.front();
257 while (current && current->next) {
258 if (current->can_merge(current->next)) {
259 QuarantineBatch *extracted = current->next;
260 // Move all the chunks into the current batch.
261 current->merge(extracted);
262 CHECK_EQ(extracted->count, 0);
263 CHECK_EQ(extracted->size, sizeof(QuarantineBatch));
264 // Remove the next batch from the list and account for its size.
265 list_.extract(current, extracted);
266 extracted_size += extracted->size;
267 // Add it to deallocation list.
268 to_deallocate->EnqueueBatch(extracted);
269 } else {
270 current = current->next;
271 }
272 }
273 SizeSub(extracted_size);
274 }
275
276 void PrintStats() const {
277 uptr batch_count = 0;
278 uptr total_overhead_bytes = 0;
279 uptr total_bytes = 0;
280 uptr total_quarantine_chunks = 0;
281 for (List::ConstIterator it = list_.begin(); it != list_.end(); ++it) {
282 batch_count++;
283 total_bytes += (*it).size;
284 total_overhead_bytes += (*it).size - (*it).quarantined_size();
285 total_quarantine_chunks += (*it).count;
286 }
287 uptr quarantine_chunks_capacity = batch_count * QuarantineBatch::kSize;
288 int chunks_usage_percent = quarantine_chunks_capacity == 0 ?
289 0 : total_quarantine_chunks * 100 / quarantine_chunks_capacity;
290 uptr total_quarantined_bytes = total_bytes - total_overhead_bytes;
291 int memory_overhead_percent = total_quarantined_bytes == 0 ?
292 0 : total_overhead_bytes * 100 / total_quarantined_bytes;
293 Printf("Global quarantine stats: batches: %zd; bytes: %zd (user: %zd); "
294 "chunks: %zd (capacity: %zd); %d%% chunks used; %d%% memory overhead"
295 "\n",
296 batch_count, total_bytes, total_quarantined_bytes,
297 total_quarantine_chunks, quarantine_chunks_capacity,
298 chunks_usage_percent, memory_overhead_percent);
299 }
300
301 private:
302 typedef IntrusiveList<QuarantineBatch> List;
303
304 List list_;
305 atomic_uintptr_t size_;
306
307 void SizeAdd(uptr add) {
308 atomic_store_relaxed(&size_, Size() + add);
309 }
310 void SizeSub(uptr sub) {
311 atomic_store_relaxed(&size_, Size() - sub);
312 }
313};
314
315} // namespace __sanitizer
316
317#endif // SANITIZER_QUARANTINE_H
lib/tsan/sanitizer_common/sanitizer_report_decorator.h created+48
...@@ -0,0 +1,48 @@
1//===-- sanitizer_report_decorator.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// Tags to decorate the sanitizer reports.
10// Currently supported tags:
11// * None.
12// * ANSI color sequences.
13//
14//===----------------------------------------------------------------------===//
15
16#ifndef SANITIZER_REPORT_DECORATOR_H
17#define SANITIZER_REPORT_DECORATOR_H
18
19#include "sanitizer_common.h"
20
21namespace __sanitizer {
22class SanitizerCommonDecorator {
23 // FIXME: This is not portable. It assumes the special strings are printed to
24 // stdout, which is not the case on Windows (see SetConsoleTextAttribute()).
25 public:
26 SanitizerCommonDecorator() : ansi_(ColorizeReports()) {}
27 const char *Bold() const { return ansi_ ? "\033[1m" : ""; }
28 const char *Default() const { return ansi_ ? "\033[1m\033[0m" : ""; }
29 const char *Warning() const { return Red(); }
30 const char *Error() const { return Red(); }
31 const char *MemoryByte() const { return Magenta(); }
32
33 protected:
34 const char *Black() const { return ansi_ ? "\033[1m\033[30m" : ""; }
35 const char *Red() const { return ansi_ ? "\033[1m\033[31m" : ""; }
36 const char *Green() const { return ansi_ ? "\033[1m\033[32m" : ""; }
37 const char *Yellow() const { return ansi_ ? "\033[1m\033[33m" : ""; }
38 const char *Blue() const { return ansi_ ? "\033[1m\033[34m" : ""; }
39 const char *Magenta() const { return ansi_ ? "\033[1m\033[35m" : ""; }
40 const char *Cyan() const { return ansi_ ? "\033[1m\033[36m" : ""; }
41 const char *White() const { return ansi_ ? "\033[1m\033[37m" : ""; }
42 private:
43 bool ansi_;
44};
45
46} // namespace __sanitizer
47
48#endif // SANITIZER_REPORT_DECORATOR_H
lib/tsan/sanitizer_common/sanitizer_ring_buffer.h created+161
...@@ -0,0 +1,161 @@
1//===-- sanitizer_ring_buffer.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// Simple ring buffer.
10//
11//===----------------------------------------------------------------------===//
12#ifndef SANITIZER_RING_BUFFER_H
13#define SANITIZER_RING_BUFFER_H
14
15#include "sanitizer_common.h"
16
17namespace __sanitizer {
18// RingBuffer<T>: fixed-size ring buffer optimized for speed of push().
19// T should be a POD type and sizeof(T) should be divisible by sizeof(void*).
20// At creation, all elements are zero.
21template<class T>
22class RingBuffer {
23 public:
24 COMPILER_CHECK(sizeof(T) % sizeof(void *) == 0);
25 static RingBuffer *New(uptr Size) {
26 void *Ptr = MmapOrDie(SizeInBytes(Size), "RingBuffer");
27 RingBuffer *RB = reinterpret_cast<RingBuffer*>(Ptr);
28 uptr End = reinterpret_cast<uptr>(Ptr) + SizeInBytes(Size);
29 RB->last_ = RB->next_ = reinterpret_cast<T*>(End - sizeof(T));
30 return RB;
31 }
32 void Delete() {
33 UnmapOrDie(this, SizeInBytes(size()));
34 }
35 uptr size() const {
36 return last_ + 1 -
37 reinterpret_cast<T *>(reinterpret_cast<uptr>(this) +
38 2 * sizeof(T *));
39 }
40
41 static uptr SizeInBytes(uptr Size) {
42 return Size * sizeof(T) + 2 * sizeof(T*);
43 }
44
45 uptr SizeInBytes() { return SizeInBytes(size()); }
46
47 void push(T t) {
48 *next_ = t;
49 next_--;
50 // The condition below works only if sizeof(T) is divisible by sizeof(T*).
51 if (next_ <= reinterpret_cast<T*>(&next_))
52 next_ = last_;
53 }
54
55 T operator[](uptr Idx) const {
56 CHECK_LT(Idx, size());
57 sptr IdxNext = Idx + 1;
58 if (IdxNext > last_ - next_)
59 IdxNext -= size();
60 return next_[IdxNext];
61 }
62
63 private:
64 RingBuffer() {}
65 ~RingBuffer() {}
66 RingBuffer(const RingBuffer&) = delete;
67
68 // Data layout:
69 // LNDDDDDDDD
70 // D: data elements.
71 // L: last_, always points to the last data element.
72 // N: next_, initially equals to last_, is decremented on every push,
73 // wraps around if it's less or equal than its own address.
74 T *last_;
75 T *next_;
76 T data_[1]; // flexible array.
77};
78
79// A ring buffer with externally provided storage that encodes its state in 8
80// bytes. Has significant constraints on size and alignment of storage.
81// See a comment in hwasan/hwasan_thread_list.h for the motivation behind this.
82#if SANITIZER_WORDSIZE == 64
83template <class T>
84class CompactRingBuffer {
85 // Top byte of long_ stores the buffer size in pages.
86 // Lower bytes store the address of the next buffer element.
87 static constexpr int kPageSizeBits = 12;
88 static constexpr int kSizeShift = 56;
89 static constexpr uptr kNextMask = (1ULL << kSizeShift) - 1;
90
91 uptr GetStorageSize() const { return (long_ >> kSizeShift) << kPageSizeBits; }
92
93 void Init(void *storage, uptr size) {
94 CHECK_EQ(sizeof(CompactRingBuffer<T>), sizeof(void *));
95 CHECK(IsPowerOfTwo(size));
96 CHECK_GE(size, 1 << kPageSizeBits);
97 CHECK_LE(size, 128 << kPageSizeBits);
98 CHECK_EQ(size % 4096, 0);
99 CHECK_EQ(size % sizeof(T), 0);
100 CHECK_EQ((uptr)storage % (size * 2), 0);
101 long_ = (uptr)storage | ((size >> kPageSizeBits) << kSizeShift);
102 }
103
104 void SetNext(const T *next) {
105 long_ = (long_ & ~kNextMask) | (uptr)next;
106 }
107
108 public:
109 CompactRingBuffer(void *storage, uptr size) {
110 Init(storage, size);
111 }
112
113 // A copy constructor of sorts.
114 CompactRingBuffer(const CompactRingBuffer &other, void *storage) {
115 uptr size = other.GetStorageSize();
116 internal_memcpy(storage, other.StartOfStorage(), size);
117 Init(storage, size);
118 uptr Idx = other.Next() - (const T *)other.StartOfStorage();
119 SetNext((const T *)storage + Idx);
120 }
121
122 T *Next() const { return (T *)(long_ & kNextMask); }
123
124 void *StartOfStorage() const {
125 return (void *)((uptr)Next() & ~(GetStorageSize() - 1));
126 }
127
128 void *EndOfStorage() const {
129 return (void *)((uptr)StartOfStorage() + GetStorageSize());
130 }
131
132 uptr size() const { return GetStorageSize() / sizeof(T); }
133
134 void push(T t) {
135 T *next = Next();
136 *next = t;
137 next++;
138 next = (T *)((uptr)next & ~GetStorageSize());
139 SetNext(next);
140 }
141
142 const T &operator[](uptr Idx) const {
143 CHECK_LT(Idx, size());
144 const T *Begin = (const T *)StartOfStorage();
145 sptr StorageIdx = Next() - Begin;
146 StorageIdx -= (sptr)(Idx + 1);
147 if (StorageIdx < 0)
148 StorageIdx += size();
149 return Begin[StorageIdx];
150 }
151
152 public:
153 ~CompactRingBuffer() {}
154 CompactRingBuffer(const CompactRingBuffer &) = delete;
155
156 uptr long_;
157};
158#endif
159} // namespace __sanitizer
160
161#endif // SANITIZER_RING_BUFFER_H
lib/tsan/sanitizer_common/sanitizer_rtems.cpp created+283
...@@ -0,0 +1,283 @@
1//===-- sanitizer_rtems.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 shared between various sanitizers' runtime libraries and
10// implements RTEMS-specific functions.
11//===----------------------------------------------------------------------===//
12
13#include "sanitizer_rtems.h"
14#if SANITIZER_RTEMS
15
16#define posix_memalign __real_posix_memalign
17#define free __real_free
18#define memset __real_memset
19
20#include "sanitizer_file.h"
21#include "sanitizer_symbolizer.h"
22#include <errno.h>
23#include <fcntl.h>
24#include <pthread.h>
25#include <sched.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <unistd.h>
30
31// There is no mmap on RTEMS. Use memalign, etc.
32#define __mmap_alloc_aligned posix_memalign
33#define __mmap_free free
34#define __mmap_memset memset
35
36namespace __sanitizer {
37
38#include "sanitizer_syscall_generic.inc"
39
40void NORETURN internal__exit(int exitcode) {
41 _exit(exitcode);
42}
43
44uptr internal_sched_yield() {
45 return sched_yield();
46}
47
48uptr internal_getpid() {
49 return getpid();
50}
51
52int internal_dlinfo(void *handle, int request, void *p) {
53 UNIMPLEMENTED();
54}
55
56bool FileExists(const char *filename) {
57 struct stat st;
58 if (stat(filename, &st))
59 return false;
60 // Sanity check: filename is a regular file.
61 return S_ISREG(st.st_mode);
62}
63
64uptr GetThreadSelf() { return static_cast<uptr>(pthread_self()); }
65
66tid_t GetTid() { return GetThreadSelf(); }
67
68void Abort() { abort(); }
69
70int Atexit(void (*function)(void)) { return atexit(function); }
71
72void SleepForSeconds(int seconds) { sleep(seconds); }
73
74void SleepForMillis(int millis) { usleep(millis * 1000); }
75
76bool SupportsColoredOutput(fd_t fd) { return false; }
77
78void GetThreadStackTopAndBottom(bool at_initialization,
79 uptr *stack_top, uptr *stack_bottom) {
80 pthread_attr_t attr;
81 pthread_attr_init(&attr);
82 CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0);
83 void *base = nullptr;
84 size_t size = 0;
85 CHECK_EQ(pthread_attr_getstack(&attr, &base, &size), 0);
86 CHECK_EQ(pthread_attr_destroy(&attr), 0);
87
88 *stack_bottom = reinterpret_cast<uptr>(base);
89 *stack_top = *stack_bottom + size;
90}
91
92void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
93 uptr *tls_addr, uptr *tls_size) {
94 uptr stack_top, stack_bottom;
95 GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
96 *stk_addr = stack_bottom;
97 *stk_size = stack_top - stack_bottom;
98 *tls_addr = *tls_size = 0;
99}
100
101void InitializePlatformEarly() {}
102void MaybeReexec() {}
103void CheckASLR() {}
104void CheckMPROTECT() {}
105void DisableCoreDumperIfNecessary() {}
106void InstallDeadlySignalHandlers(SignalHandlerType handler) {}
107void SetAlternateSignalStack() {}
108void UnsetAlternateSignalStack() {}
109void InitTlsSize() {}
110
111void PrintModuleMap() {}
112
113void SignalContext::DumpAllRegisters(void *context) {}
114const char *DescribeSignalOrException(int signo) { UNIMPLEMENTED(); }
115
116enum MutexState { MtxUnlocked = 0, MtxLocked = 1, MtxSleeping = 2 };
117
118BlockingMutex::BlockingMutex() {
119 internal_memset(this, 0, sizeof(*this));
120}
121
122void BlockingMutex::Lock() {
123 CHECK_EQ(owner_, 0);
124 atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
125 if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked)
126 return;
127 while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked) {
128 internal_sched_yield();
129 }
130}
131
132void BlockingMutex::Unlock() {
133 atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
134 u32 v = atomic_exchange(m, MtxUnlocked, memory_order_release);
135 CHECK_NE(v, MtxUnlocked);
136}
137
138void BlockingMutex::CheckLocked() {
139 atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
140 CHECK_NE(MtxUnlocked, atomic_load(m, memory_order_relaxed));
141}
142
143uptr GetPageSize() { return getpagesize(); }
144
145uptr GetMmapGranularity() { return GetPageSize(); }
146
147uptr GetMaxVirtualAddress() {
148 return (1ULL << 32) - 1; // 0xffffffff
149}
150
151void *MmapOrDie(uptr size, const char *mem_type, bool raw_report) {
152 void* ptr = 0;
153 int res = __mmap_alloc_aligned(&ptr, GetPageSize(), size);
154 if (UNLIKELY(res))
155 ReportMmapFailureAndDie(size, mem_type, "allocate", res, raw_report);
156 __mmap_memset(ptr, 0, size);
157 IncreaseTotalMmap(size);
158 return ptr;
159}
160
161void *MmapOrDieOnFatalError(uptr size, const char *mem_type) {
162 void* ptr = 0;
163 int res = __mmap_alloc_aligned(&ptr, GetPageSize(), size);
164 if (UNLIKELY(res)) {
165 if (res == ENOMEM)
166 return nullptr;
167 ReportMmapFailureAndDie(size, mem_type, "allocate", false);
168 }
169 __mmap_memset(ptr, 0, size);
170 IncreaseTotalMmap(size);
171 return ptr;
172}
173
174void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment,
175 const char *mem_type) {
176 CHECK(IsPowerOfTwo(size));
177 CHECK(IsPowerOfTwo(alignment));
178 void* ptr = 0;
179 int res = __mmap_alloc_aligned(&ptr, alignment, size);
180 if (res)
181 ReportMmapFailureAndDie(size, mem_type, "align allocate", res, false);
182 __mmap_memset(ptr, 0, size);
183 IncreaseTotalMmap(size);
184 return ptr;
185}
186
187void *MmapNoReserveOrDie(uptr size, const char *mem_type) {
188 return MmapOrDie(size, mem_type, false);
189}
190
191void UnmapOrDie(void *addr, uptr size) {
192 if (!addr || !size) return;
193 __mmap_free(addr);
194 DecreaseTotalMmap(size);
195}
196
197fd_t OpenFile(const char *filename, FileAccessMode mode, error_t *errno_p) {
198 int flags;
199 switch (mode) {
200 case RdOnly: flags = O_RDONLY; break;
201 case WrOnly: flags = O_WRONLY | O_CREAT | O_TRUNC; break;
202 case RdWr: flags = O_RDWR | O_CREAT; break;
203 }
204 fd_t res = open(filename, flags, 0660);
205 if (internal_iserror(res, errno_p))
206 return kInvalidFd;
207 return res;
208}
209
210void CloseFile(fd_t fd) {
211 close(fd);
212}
213
214bool ReadFromFile(fd_t fd, void *buff, uptr buff_size, uptr *bytes_read,
215 error_t *error_p) {
216 uptr res = read(fd, buff, buff_size);
217 if (internal_iserror(res, error_p))
218 return false;
219 if (bytes_read)
220 *bytes_read = res;
221 return true;
222}
223
224bool WriteToFile(fd_t fd, const void *buff, uptr buff_size, uptr *bytes_written,
225 error_t *error_p) {
226 uptr res = write(fd, buff, buff_size);
227 if (internal_iserror(res, error_p))
228 return false;
229 if (bytes_written)
230 *bytes_written = res;
231 return true;
232}
233
234void ReleaseMemoryPagesToOS(uptr beg, uptr end) {}
235void DumpProcessMap() {}
236
237// There is no page protection so everything is "accessible."
238bool IsAccessibleMemoryRange(uptr beg, uptr size) {
239 return true;
240}
241
242char **GetArgv() { return nullptr; }
243char **GetEnviron() { return nullptr; }
244
245const char *GetEnv(const char *name) {
246 return getenv(name);
247}
248
249uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
250 internal_strncpy(buf, "StubBinaryName", buf_len);
251 return internal_strlen(buf);
252}
253
254uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len) {
255 internal_strncpy(buf, "StubProcessName", buf_len);
256 return internal_strlen(buf);
257}
258
259bool IsPathSeparator(const char c) {
260 return c == '/';
261}
262
263bool IsAbsolutePath(const char *path) {
264 return path != nullptr && IsPathSeparator(path[0]);
265}
266
267void ReportFile::Write(const char *buffer, uptr length) {
268 SpinMutexLock l(mu);
269 static const char *kWriteError =
270 "ReportFile::Write() can't output requested buffer!\n";
271 ReopenIfNecessary();
272 if (length != write(fd, buffer, length)) {
273 write(fd, kWriteError, internal_strlen(kWriteError));
274 Die();
275 }
276}
277
278uptr MainThreadStackBase, MainThreadStackSize;
279uptr MainThreadTlsBase, MainThreadTlsSize;
280
281} // namespace __sanitizer
282
283#endif // SANITIZER_RTEMS
lib/tsan/sanitizer_common/sanitizer_rtems.h created+20
...@@ -0,0 +1,20 @@
1//===-- sanitizer_rtems.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 various sanitizers' runtime libraries and
10// provides definitions for RTEMS-specific functions.
11//===----------------------------------------------------------------------===//
12#ifndef SANITIZER_RTEMS_H
13#define SANITIZER_RTEMS_H
14
15#include "sanitizer_platform.h"
16#if SANITIZER_RTEMS
17#include "sanitizer_common.h"
18
19#endif // SANITIZER_RTEMS
20#endif // SANITIZER_RTEMS_H
lib/tsan/sanitizer_common/sanitizer_signal_interceptors.inc created+86
...@@ -0,0 +1,86 @@
1//===-- sanitizer_signal_interceptors.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// Signal interceptors for sanitizers.
10//
11//===----------------------------------------------------------------------===//
12
13#include "interception/interception.h"
14#include "sanitizer_common.h"
15#include "sanitizer_internal_defs.h"
16#include "sanitizer_platform_interceptors.h"
17
18using namespace __sanitizer;
19
20#if SANITIZER_NETBSD
21#define sigaction_symname __sigaction14
22#else
23#define sigaction_symname sigaction
24#endif
25
26#ifndef SIGNAL_INTERCEPTOR_SIGNAL_IMPL
27#define SIGNAL_INTERCEPTOR_SIGNAL_IMPL(func, signum, handler) \
28 { return REAL(func)(signum, handler); }
29#endif
30
31#ifndef SIGNAL_INTERCEPTOR_SIGACTION_IMPL
32#define SIGNAL_INTERCEPTOR_SIGACTION_IMPL(signum, act, oldact) \
33 { return REAL(sigaction_symname)(signum, act, oldact); }
34#endif
35
36#if SANITIZER_INTERCEPT_BSD_SIGNAL
37INTERCEPTOR(uptr, bsd_signal, int signum, uptr handler) {
38 if (GetHandleSignalMode(signum) == kHandleSignalExclusive) return 0;
39 SIGNAL_INTERCEPTOR_SIGNAL_IMPL(bsd_signal, signum, handler);
40}
41#define INIT_BSD_SIGNAL COMMON_INTERCEPT_FUNCTION(bsd_signal)
42#else // SANITIZER_INTERCEPT_BSD_SIGNAL
43#define INIT_BSD_SIGNAL
44#endif // SANITIZER_INTERCEPT_BSD_SIGNAL
45
46#if SANITIZER_INTERCEPT_SIGNAL_AND_SIGACTION
47INTERCEPTOR(uptr, signal, int signum, uptr handler) {
48 if (GetHandleSignalMode(signum) == kHandleSignalExclusive)
49 return (uptr) nullptr;
50 SIGNAL_INTERCEPTOR_SIGNAL_IMPL(signal, signum, handler);
51}
52#define INIT_SIGNAL COMMON_INTERCEPT_FUNCTION(signal)
53
54INTERCEPTOR(int, sigaction_symname, int signum,
55 const __sanitizer_sigaction *act, __sanitizer_sigaction *oldact) {
56 if (GetHandleSignalMode(signum) == kHandleSignalExclusive) return 0;
57 SIGNAL_INTERCEPTOR_SIGACTION_IMPL(signum, act, oldact);
58}
59#define INIT_SIGACTION COMMON_INTERCEPT_FUNCTION(sigaction_symname)
60
61namespace __sanitizer {
62int real_sigaction(int signum, const void *act, void *oldact) {
63 return REAL(sigaction_symname)(signum, (const __sanitizer_sigaction *)act,
64 (__sanitizer_sigaction *)oldact);
65}
66} // namespace __sanitizer
67#else // SANITIZER_INTERCEPT_SIGNAL_AND_SIGACTION
68#define INIT_SIGNAL
69#define INIT_SIGACTION
70// We need to have defined REAL(sigaction) on other systems.
71namespace __sanitizer {
72struct __sanitizer_sigaction;
73}
74DEFINE_REAL(int, sigaction, int signum, const __sanitizer_sigaction *act,
75 __sanitizer_sigaction *oldact)
76#endif // SANITIZER_INTERCEPT_SIGNAL_AND_SIGACTION
77
78static void InitializeSignalInterceptors() {
79 static bool was_called_once;
80 CHECK(!was_called_once);
81 was_called_once = true;
82
83 INIT_BSD_SIGNAL;
84 INIT_SIGNAL;
85 INIT_SIGACTION;
86}
lib/tsan/sanitizer_common/sanitizer_solaris.cpp created+230
...@@ -0,0 +1,230 @@
1//===-- sanitizer_solaris.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 shared between various sanitizers' runtime libraries and
10// implements Solaris-specific functions.
11//===----------------------------------------------------------------------===//
12
13#include "sanitizer_platform.h"
14#if SANITIZER_SOLARIS
15
16#include <stdio.h>
17
18#include "sanitizer_common.h"
19#include "sanitizer_flags.h"
20#include "sanitizer_internal_defs.h"
21#include "sanitizer_libc.h"
22#include "sanitizer_placement_new.h"
23#include "sanitizer_platform_limits_posix.h"
24#include "sanitizer_procmaps.h"
25
26#include <fcntl.h>
27#include <pthread.h>
28#include <sched.h>
29#include <thread.h>
30#include <synch.h>
31#include <signal.h>
32#include <sys/mman.h>
33#include <sys/resource.h>
34#include <sys/stat.h>
35#include <sys/types.h>
36#include <dirent.h>
37#include <unistd.h>
38#include <errno.h>
39#include <stdlib.h>
40
41namespace __sanitizer {
42
43//#include "sanitizer_syscall_generic.inc"
44
45#define _REAL(func) _ ## func
46#define DECLARE__REAL(ret_type, func, ...) \
47 extern "C" ret_type _REAL(func)(__VA_ARGS__)
48#define DECLARE__REAL_AND_INTERNAL(ret_type, func, ...) \
49 DECLARE__REAL(ret_type, func, __VA_ARGS__); \
50 ret_type internal_ ## func(__VA_ARGS__)
51
52#if !defined(_LP64) && _FILE_OFFSET_BITS == 64
53#define _REAL64(func) _ ## func ## 64
54#else
55#define _REAL64(func) _REAL(func)
56#endif
57#define DECLARE__REAL64(ret_type, func, ...) \
58 extern "C" ret_type _REAL64(func)(__VA_ARGS__)
59#define DECLARE__REAL_AND_INTERNAL64(ret_type, func, ...) \
60 DECLARE__REAL64(ret_type, func, __VA_ARGS__); \
61 ret_type internal_ ## func(__VA_ARGS__)
62
63// ---------------------- sanitizer_libc.h
64DECLARE__REAL_AND_INTERNAL64(uptr, mmap, void *addr, uptr /*size_t*/ length,
65 int prot, int flags, int fd, OFF_T offset) {
66 return (uptr)_REAL64(mmap)(addr, length, prot, flags, fd, offset);
67}
68
69DECLARE__REAL_AND_INTERNAL(uptr, munmap, void *addr, uptr length) {
70 return _REAL(munmap)(addr, length);
71}
72
73DECLARE__REAL_AND_INTERNAL(int, mprotect, void *addr, uptr length, int prot) {
74 return _REAL(mprotect)(addr, length, prot);
75}
76
77DECLARE__REAL_AND_INTERNAL(uptr, close, fd_t fd) {
78 return _REAL(close)(fd);
79}
80
81extern "C" int _REAL64(open)(const char *, int, ...);
82
83uptr internal_open(const char *filename, int flags) {
84 return _REAL64(open)(filename, flags);
85}
86
87uptr internal_open(const char *filename, int flags, u32 mode) {
88 return _REAL64(open)(filename, flags, mode);
89}
90
91DECLARE__REAL_AND_INTERNAL(uptr, read, fd_t fd, void *buf, uptr count) {
92 return _REAL(read)(fd, buf, count);
93}
94
95DECLARE__REAL_AND_INTERNAL(uptr, write, fd_t fd, const void *buf, uptr count) {
96 return _REAL(write)(fd, buf, count);
97}
98
99// FIXME: There's only _ftruncate64 beginning with Solaris 11.
100DECLARE__REAL_AND_INTERNAL(uptr, ftruncate, fd_t fd, uptr size) {
101 return ftruncate(fd, size);
102}
103
104DECLARE__REAL_AND_INTERNAL64(uptr, stat, const char *path, void *buf) {
105 return _REAL64(stat)(path, (struct stat *)buf);
106}
107
108DECLARE__REAL_AND_INTERNAL64(uptr, lstat, const char *path, void *buf) {
109 return _REAL64(lstat)(path, (struct stat *)buf);
110}
111
112DECLARE__REAL_AND_INTERNAL64(uptr, fstat, fd_t fd, void *buf) {
113 return _REAL64(fstat)(fd, (struct stat *)buf);
114}
115
116uptr internal_filesize(fd_t fd) {
117 struct stat st;
118 if (internal_fstat(fd, &st))
119 return -1;
120 return (uptr)st.st_size;
121}
122
123DECLARE__REAL_AND_INTERNAL(uptr, dup, int oldfd) {
124 return _REAL(dup)(oldfd);
125}
126
127DECLARE__REAL_AND_INTERNAL(uptr, dup2, int oldfd, int newfd) {
128 return _REAL(dup2)(oldfd, newfd);
129}
130
131DECLARE__REAL_AND_INTERNAL(uptr, readlink, const char *path, char *buf,
132 uptr bufsize) {
133 return _REAL(readlink)(path, buf, bufsize);
134}
135
136DECLARE__REAL_AND_INTERNAL(uptr, unlink, const char *path) {
137 return _REAL(unlink)(path);
138}
139
140DECLARE__REAL_AND_INTERNAL(uptr, rename, const char *oldpath,
141 const char *newpath) {
142 return _REAL(rename)(oldpath, newpath);
143}
144
145DECLARE__REAL_AND_INTERNAL(uptr, sched_yield, void) {
146 return sched_yield();
147}
148
149DECLARE__REAL_AND_INTERNAL(void, _exit, int exitcode) {
150 _exit(exitcode);
151}
152
153DECLARE__REAL_AND_INTERNAL(uptr, execve, const char *filename,
154 char *const argv[], char *const envp[]) {
155 return _REAL(execve)(filename, argv, envp);
156}
157
158DECLARE__REAL_AND_INTERNAL(uptr, waitpid, int pid, int *status, int options) {
159 return _REAL(waitpid)(pid, status, options);
160}
161
162DECLARE__REAL_AND_INTERNAL(uptr, getpid, void) {
163 return _REAL(getpid)();
164}
165
166// FIXME: This might be wrong: _getdents doesn't take a struct linux_dirent *.
167DECLARE__REAL_AND_INTERNAL64(uptr, getdents, fd_t fd, struct linux_dirent *dirp,
168 unsigned int count) {
169 return _REAL64(getdents)(fd, dirp, count);
170}
171
172DECLARE__REAL_AND_INTERNAL64(uptr, lseek, fd_t fd, OFF_T offset, int whence) {
173 return _REAL64(lseek)(fd, offset, whence);
174}
175
176// FIXME: This might be wrong: _sigfillset doesn't take a
177// __sanitizer_sigset_t *.
178DECLARE__REAL_AND_INTERNAL(void, sigfillset, __sanitizer_sigset_t *set) {
179 _REAL(sigfillset)(set);
180}
181
182// FIXME: This might be wrong: _sigprocmask doesn't take __sanitizer_sigset_t *.
183DECLARE__REAL_AND_INTERNAL(uptr, sigprocmask, int how,
184 __sanitizer_sigset_t *set,
185 __sanitizer_sigset_t *oldset) {
186 return _REAL(sigprocmask)(how, set, oldset);
187}
188
189DECLARE__REAL_AND_INTERNAL(int, fork, void) {
190 // TODO(glider): this may call user's pthread_atfork() handlers which is bad.
191 return _REAL(fork)();
192}
193
194u64 NanoTime() {
195 return gethrtime();
196}
197
198uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp) {
199 // FIXME: No internal variant.
200 return clock_gettime(clk_id, (timespec *)tp);
201}
202
203// ----------------- sanitizer_common.h
204BlockingMutex::BlockingMutex() {
205 CHECK(sizeof(mutex_t) <= sizeof(opaque_storage_));
206 internal_memset(this, 0, sizeof(*this));
207 CHECK_EQ(mutex_init((mutex_t *)&opaque_storage_, USYNC_THREAD, NULL), 0);
208}
209
210void BlockingMutex::Lock() {
211 CHECK(sizeof(mutex_t) <= sizeof(opaque_storage_));
212 CHECK_NE(owner_, (uptr)thr_self());
213 CHECK_EQ(mutex_lock((mutex_t *)&opaque_storage_), 0);
214 CHECK(!owner_);
215 owner_ = (uptr)thr_self();
216}
217
218void BlockingMutex::Unlock() {
219 CHECK(owner_ == (uptr)thr_self());
220 owner_ = 0;
221 CHECK_EQ(mutex_unlock((mutex_t *)&opaque_storage_), 0);
222}
223
224void BlockingMutex::CheckLocked() {
225 CHECK_EQ((uptr)thr_self(), owner_);
226}
227
228} // namespace __sanitizer
229
230#endif // SANITIZER_SOLARIS
lib/tsan/sanitizer_common/sanitizer_stackdepot.h created+71
...@@ -0,0 +1,71 @@
1//===-- sanitizer_stackdepot.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 AddressSanitizer and ThreadSanitizer
10// run-time libraries.
11//===----------------------------------------------------------------------===//
12
13#ifndef SANITIZER_STACKDEPOT_H
14#define SANITIZER_STACKDEPOT_H
15
16#include "sanitizer_common.h"
17#include "sanitizer_internal_defs.h"
18#include "sanitizer_stacktrace.h"
19
20namespace __sanitizer {
21
22// StackDepot efficiently stores huge amounts of stack traces.
23struct StackDepotNode;
24struct 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();
31 void inc_use_count_unsafe();
32};
33
34const int kStackDepotMaxUseCount = 1U << (SANITIZER_ANDROID ? 16 : 20);
35
36StackDepotStats *StackDepotGetStats();
37u32 StackDepotPut(StackTrace stack);
38StackDepotHandle StackDepotPut_WithHandle(StackTrace stack);
39// Retrieves a stored stack trace by the id.
40StackTrace StackDepotGet(u32 id);
41
42void StackDepotLockAll();
43void StackDepotUnlockAll();
44
45// Instantiating this class creates a snapshot of StackDepot which can be
46// efficiently queried with StackDepotGet(). You can use it concurrently with
47// StackDepot, but the snapshot is only guaranteed to contain those stack traces
48// which were stored before it was instantiated.
49class StackDepotReverseMap {
50 public:
51 StackDepotReverseMap();
52 StackTrace Get(u32 id);
53
54 private:
55 struct IdDescPair {
56 u32 id;
57 StackDepotNode *desc;
58
59 static bool IdComparator(const IdDescPair &a, const IdDescPair &b);
60 };
61
62 InternalMmapVector<IdDescPair> map_;
63
64 // Disallow evil constructors.
65 StackDepotReverseMap(const StackDepotReverseMap&);
66 void operator=(const StackDepotReverseMap&);
67};
68
69} // namespace __sanitizer
70
71#endif // SANITIZER_STACKDEPOT_H
lib/tsan/sanitizer_common/sanitizer_stackdepotbase.h created+177
...@@ -0,0 +1,177 @@
1//===-- sanitizer_stackdepotbase.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// Implementation of a mapping from arbitrary values to unique 32-bit
10// identifiers.
11//===----------------------------------------------------------------------===//
12
13#ifndef SANITIZER_STACKDEPOTBASE_H
14#define SANITIZER_STACKDEPOTBASE_H
15
16#include "sanitizer_internal_defs.h"
17#include "sanitizer_mutex.h"
18#include "sanitizer_atomic.h"
19#include "sanitizer_persistent_allocator.h"
20
21namespace __sanitizer {
22
23template <class Node, int kReservedBits, int kTabSizeLog>
24class StackDepotBase {
25 public:
26 typedef typename Node::args_type args_type;
27 typedef typename Node::handle_type handle_type;
28 // Maps stack trace to an unique id.
29 handle_type Put(args_type args, bool *inserted = nullptr);
30 // Retrieves a stored stack trace by the id.
31 args_type Get(u32 id);
32
33 StackDepotStats *GetStats() { return &stats; }
34
35 void LockAll();
36 void UnlockAll();
37
38 private:
39 static Node *find(Node *s, args_type args, u32 hash);
40 static Node *lock(atomic_uintptr_t *p);
41 static void unlock(atomic_uintptr_t *p, Node *s);
42
43 static const int kTabSize = 1 << kTabSizeLog; // Hash table size.
44 static const int kPartBits = 8;
45 static const int kPartShift = sizeof(u32) * 8 - kPartBits - kReservedBits;
46 static const int kPartCount =
47 1 << kPartBits; // Number of subparts in the table.
48 static const int kPartSize = kTabSize / kPartCount;
49 static const int kMaxId = 1 << kPartShift;
50
51 atomic_uintptr_t tab[kTabSize]; // Hash table of Node's.
52 atomic_uint32_t seq[kPartCount]; // Unique id generators.
53
54 StackDepotStats stats;
55
56 friend class StackDepotReverseMap;
57};
58
59template <class Node, int kReservedBits, int kTabSizeLog>
60Node *StackDepotBase<Node, kReservedBits, kTabSizeLog>::find(Node *s,
61 args_type args,
62 u32 hash) {
63 // Searches linked list s for the stack, returns its id.
64 for (; s; s = s->link) {
65 if (s->eq(hash, args)) {
66 return s;
67 }
68 }
69 return nullptr;
70}
71
72template <class Node, int kReservedBits, int kTabSizeLog>
73Node *StackDepotBase<Node, kReservedBits, kTabSizeLog>::lock(
74 atomic_uintptr_t *p) {
75 // Uses the pointer lsb as mutex.
76 for (int i = 0;; i++) {
77 uptr cmp = atomic_load(p, memory_order_relaxed);
78 if ((cmp & 1) == 0 &&
79 atomic_compare_exchange_weak(p, &cmp, cmp | 1, memory_order_acquire))
80 return (Node *)cmp;
81 if (i < 10)
82 proc_yield(10);
83 else
84 internal_sched_yield();
85 }
86}
87
88template <class Node, int kReservedBits, int kTabSizeLog>
89void StackDepotBase<Node, kReservedBits, kTabSizeLog>::unlock(
90 atomic_uintptr_t *p, Node *s) {
91 DCHECK_EQ((uptr)s & 1, 0);
92 atomic_store(p, (uptr)s, memory_order_release);
93}
94
95template <class Node, int kReservedBits, int kTabSizeLog>
96typename StackDepotBase<Node, kReservedBits, kTabSizeLog>::handle_type
97StackDepotBase<Node, kReservedBits, kTabSizeLog>::Put(args_type args,
98 bool *inserted) {
99 if (inserted) *inserted = false;
100 if (!Node::is_valid(args)) return handle_type();
101 uptr h = Node::hash(args);
102 atomic_uintptr_t *p = &tab[h % kTabSize];
103 uptr v = atomic_load(p, memory_order_consume);
104 Node *s = (Node *)(v & ~1);
105 // First, try to find the existing stack.
106 Node *node = find(s, args, h);
107 if (node) return node->get_handle();
108 // If failed, lock, retry and insert new.
109 Node *s2 = lock(p);
110 if (s2 != s) {
111 node = find(s2, args, h);
112 if (node) {
113 unlock(p, s2);
114 return node->get_handle();
115 }
116 }
117 uptr part = (h % kTabSize) / kPartSize;
118 u32 id = atomic_fetch_add(&seq[part], 1, memory_order_relaxed) + 1;
119 stats.n_uniq_ids++;
120 CHECK_LT(id, kMaxId);
121 id |= part << kPartShift;
122 CHECK_NE(id, 0);
123 CHECK_EQ(id & (((u32)-1) >> kReservedBits), id);
124 uptr memsz = Node::storage_size(args);
125 s = (Node *)PersistentAlloc(memsz);
126 stats.allocated += memsz;
127 s->id = id;
128 s->store(args, h);
129 s->link = s2;
130 unlock(p, s);
131 if (inserted) *inserted = true;
132 return s->get_handle();
133}
134
135template <class Node, int kReservedBits, int kTabSizeLog>
136typename StackDepotBase<Node, kReservedBits, kTabSizeLog>::args_type
137StackDepotBase<Node, kReservedBits, kTabSizeLog>::Get(u32 id) {
138 if (id == 0) {
139 return args_type();
140 }
141 CHECK_EQ(id & (((u32)-1) >> kReservedBits), id);
142 // High kPartBits contain part id, so we need to scan at most kPartSize lists.
143 uptr part = id >> kPartShift;
144 for (int i = 0; i != kPartSize; i++) {
145 uptr idx = part * kPartSize + i;
146 CHECK_LT(idx, kTabSize);
147 atomic_uintptr_t *p = &tab[idx];
148 uptr v = atomic_load(p, memory_order_consume);
149 Node *s = (Node *)(v & ~1);
150 for (; s; s = s->link) {
151 if (s->id == id) {
152 return s->load();
153 }
154 }
155 }
156 return args_type();
157}
158
159template <class Node, int kReservedBits, int kTabSizeLog>
160void StackDepotBase<Node, kReservedBits, kTabSizeLog>::LockAll() {
161 for (int i = 0; i < kTabSize; ++i) {
162 lock(&tab[i]);
163 }
164}
165
166template <class Node, int kReservedBits, int kTabSizeLog>
167void StackDepotBase<Node, kReservedBits, kTabSizeLog>::UnlockAll() {
168 for (int i = 0; i < kTabSize; ++i) {
169 atomic_uintptr_t *p = &tab[i];
170 uptr s = atomic_load(p, memory_order_relaxed);
171 unlock(p, (Node *)(s & ~1UL));
172 }
173}
174
175} // namespace __sanitizer
176
177#endif // SANITIZER_STACKDEPOTBASE_H
lib/tsan/sanitizer_common/sanitizer_stacktrace.h created+176
...@@ -0,0 +1,176 @@
1//===-- sanitizer_stacktrace.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 AddressSanitizer and ThreadSanitizer
10// run-time libraries.
11//===----------------------------------------------------------------------===//
12#ifndef SANITIZER_STACKTRACE_H
13#define SANITIZER_STACKTRACE_H
14
15#include "sanitizer_internal_defs.h"
16
17namespace __sanitizer {
18
19struct BufferedStackTrace;
20
21static const u32 kStackTraceMax = 256;
22
23#if SANITIZER_LINUX && defined(__mips__)
24# define SANITIZER_CAN_FAST_UNWIND 0
25#elif SANITIZER_WINDOWS
26# define SANITIZER_CAN_FAST_UNWIND 0
27#elif SANITIZER_OPENBSD
28# define SANITIZER_CAN_FAST_UNWIND 0
29#else
30# define SANITIZER_CAN_FAST_UNWIND 1
31#endif
32
33// Fast unwind is the only option on Mac for now; we will need to
34// revisit this macro when slow unwind works on Mac, see
35// https://github.com/google/sanitizers/issues/137
36#if SANITIZER_MAC || SANITIZER_OPENBSD || SANITIZER_RTEMS
37# define SANITIZER_CAN_SLOW_UNWIND 0
38#else
39# define SANITIZER_CAN_SLOW_UNWIND 1
40#endif
41
42struct StackTrace {
43 const uptr *trace;
44 u32 size;
45 u32 tag;
46
47 static const int TAG_UNKNOWN = 0;
48 static const int TAG_ALLOC = 1;
49 static const int TAG_DEALLOC = 2;
50 static const int TAG_CUSTOM = 100; // Tool specific tags start here.
51
52 StackTrace() : trace(nullptr), size(0), tag(0) {}
53 StackTrace(const uptr *trace, u32 size) : trace(trace), size(size), tag(0) {}
54 StackTrace(const uptr *trace, u32 size, u32 tag)
55 : trace(trace), size(size), tag(tag) {}
56
57 // Prints a symbolized stacktrace, followed by an empty line.
58 void Print() const;
59
60 static bool WillUseFastUnwind(bool request_fast_unwind) {
61 if (!SANITIZER_CAN_FAST_UNWIND)
62 return false;
63 if (!SANITIZER_CAN_SLOW_UNWIND)
64 return true;
65 return request_fast_unwind;
66 }
67
68 static uptr GetCurrentPc();
69 static inline uptr GetPreviousInstructionPc(uptr pc);
70 static uptr GetNextInstructionPc(uptr pc);
71 typedef bool (*SymbolizeCallback)(const void *pc, char *out_buffer,
72 int out_size);
73};
74
75// Performance-critical, must be in the header.
76ALWAYS_INLINE
77uptr StackTrace::GetPreviousInstructionPc(uptr pc) {
78#if defined(__arm__)
79 // T32 (Thumb) branch instructions might be 16 or 32 bit long,
80 // so we return (pc-2) in that case in order to be safe.
81 // For A32 mode we return (pc-4) because all instructions are 32 bit long.
82 return (pc - 3) & (~1);
83#elif defined(__powerpc__) || defined(__powerpc64__) || defined(__aarch64__)
84 // PCs are always 4 byte aligned.
85 return pc - 4;
86#elif defined(__sparc__) || defined(__mips__)
87 return pc - 8;
88#else
89 return pc - 1;
90#endif
91}
92
93// StackTrace that owns the buffer used to store the addresses.
94struct BufferedStackTrace : public StackTrace {
95 uptr trace_buffer[kStackTraceMax];
96 uptr top_frame_bp; // Optional bp of a top frame.
97
98 BufferedStackTrace() : StackTrace(trace_buffer, 0), top_frame_bp(0) {}
99
100 void Init(const uptr *pcs, uptr cnt, uptr extra_top_pc = 0);
101
102 // Get the stack trace with the given pc and bp.
103 // The pc will be in the position 0 of the resulting stack trace.
104 // The bp may refer to the current frame or to the caller's frame.
105 void Unwind(uptr pc, uptr bp, void *context, bool request_fast,
106 u32 max_depth = kStackTraceMax) {
107 top_frame_bp = (max_depth > 0) ? bp : 0;
108 // Small max_depth optimization
109 if (max_depth <= 1) {
110 if (max_depth == 1)
111 trace_buffer[0] = pc;
112 size = max_depth;
113 return;
114 }
115 UnwindImpl(pc, bp, context, request_fast, max_depth);
116 }
117
118 void Unwind(u32 max_depth, uptr pc, uptr bp, void *context, uptr stack_top,
119 uptr stack_bottom, bool request_fast_unwind);
120
121 void Reset() {
122 *static_cast<StackTrace *>(this) = StackTrace(trace_buffer, 0);
123 top_frame_bp = 0;
124 }
125
126 private:
127 // Every runtime defines its own implementation of this method
128 void UnwindImpl(uptr pc, uptr bp, void *context, bool request_fast,
129 u32 max_depth);
130
131 // UnwindFast/Slow have platform-specific implementations
132 void UnwindFast(uptr pc, uptr bp, uptr stack_top, uptr stack_bottom,
133 u32 max_depth);
134 void UnwindSlow(uptr pc, u32 max_depth);
135 void UnwindSlow(uptr pc, void *context, u32 max_depth);
136
137 void PopStackFrames(uptr count);
138 uptr LocatePcInTrace(uptr pc);
139
140 BufferedStackTrace(const BufferedStackTrace &) = delete;
141 void operator=(const BufferedStackTrace &) = delete;
142
143 friend class FastUnwindTest;
144};
145
146// Check if given pointer points into allocated stack area.
147static inline bool IsValidFrame(uptr frame, uptr stack_top, uptr stack_bottom) {
148 return frame > stack_bottom && frame < stack_top - 2 * sizeof (uhwptr);
149}
150
151} // namespace __sanitizer
152
153// Use this macro if you want to print stack trace with the caller
154// of the current function in the top frame.
155#define GET_CALLER_PC_BP \
156 uptr bp = GET_CURRENT_FRAME(); \
157 uptr pc = GET_CALLER_PC();
158
159#define GET_CALLER_PC_BP_SP \
160 GET_CALLER_PC_BP; \
161 uptr local_stack; \
162 uptr sp = (uptr)&local_stack
163
164// Use this macro if you want to print stack trace with the current
165// function in the top frame.
166#define GET_CURRENT_PC_BP \
167 uptr bp = GET_CURRENT_FRAME(); \
168 uptr pc = StackTrace::GetCurrentPc()
169
170#define GET_CURRENT_PC_BP_SP \
171 GET_CURRENT_PC_BP; \
172 uptr local_stack; \
173 uptr sp = (uptr)&local_stack
174
175
176#endif // SANITIZER_STACKTRACE_H
lib/tsan/sanitizer_common/sanitizer_stacktrace_printer.h created+71
...@@ -0,0 +1,71 @@
1//===-- sanitizer_stacktrace_printer.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 sanitizers' run-time libraries.
10//
11//===----------------------------------------------------------------------===//
12#ifndef SANITIZER_STACKTRACE_PRINTER_H
13#define SANITIZER_STACKTRACE_PRINTER_H
14
15#include "sanitizer_common.h"
16#include "sanitizer_symbolizer.h"
17
18namespace __sanitizer {
19
20// Render the contents of "info" structure, which represents the contents of
21// stack frame "frame_no" and appends it to the "buffer". "format" is a
22// string with placeholders, which is copied to the output with
23// placeholders substituted with the contents of "info". For example,
24// format string
25// " frame %n: function %F at %S"
26// will be turned into
27// " frame 10: function foo::bar() at my/file.cc:10"
28// 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.
31// Here's the full list of available placeholders:
32// %% - represents a '%' character;
33// %n - frame number (copy of frame_no);
34// %p - PC in hex format;
35// %m - path to module (binary or shared object);
36// %o - offset in the module in hex format;
37// %f - function name;
38// %q - offset in the function in hex format (*if available*);
39// %s - path to source file;
40// %l - line in the source file;
41// %c - column in the source file;
42// %F - if function is known to be <foo>, prints "in <foo>", possibly
43// followed by the offset in this function, but only if source file
44// is unknown;
45// %S - prints file/line/column information;
46// %L - prints location information: file/line/column, if it is known, or
47// module+offset if it is known, or (<unknown module>) string.
48// %M - prints module basename and offset, if it is known, or PC.
49void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
50 const AddressInfo &info, bool vs_style,
51 const char *strip_path_prefix = "",
52 const char *strip_func_prefix = "");
53
54void RenderSourceLocation(InternalScopedString *buffer, const char *file,
55 int line, int column, bool vs_style,
56 const char *strip_path_prefix);
57
58void RenderModuleLocation(InternalScopedString *buffer, const char *module,
59 uptr offset, ModuleArch arch,
60 const char *strip_path_prefix);
61
62// Same as RenderFrame, but for data section (global variables).
63// Accepts %s, %l from above.
64// Also accepts:
65// %g - name of the global variable.
66void RenderData(InternalScopedString *buffer, const char *format,
67 const DataInfo *DI, const char *strip_path_prefix = "");
68
69} // namespace __sanitizer
70
71#endif // SANITIZER_STACKTRACE_PRINTER_H
lib/tsan/sanitizer_common/sanitizer_stoptheworld.h created+64
...@@ -0,0 +1,64 @@
1//===-- sanitizer_stoptheworld.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// Defines the StopTheWorld function which suspends the execution of the current
10// process and runs the user-supplied callback in the same address space.
11//
12//===----------------------------------------------------------------------===//
13#ifndef SANITIZER_STOPTHEWORLD_H
14#define SANITIZER_STOPTHEWORLD_H
15
16#include "sanitizer_internal_defs.h"
17#include "sanitizer_common.h"
18
19namespace __sanitizer {
20
21enum PtraceRegistersStatus {
22 REGISTERS_UNAVAILABLE_FATAL = -1,
23 REGISTERS_UNAVAILABLE = 0,
24 REGISTERS_AVAILABLE = 1
25};
26
27// Holds the list of suspended threads and provides an interface to dump their
28// register contexts.
29class SuspendedThreadsList {
30 public:
31 SuspendedThreadsList() = default;
32
33 // Can't declare pure virtual functions in sanitizer runtimes:
34 // __cxa_pure_virtual might be unavailable. Use UNIMPLEMENTED() instead.
35 virtual PtraceRegistersStatus GetRegistersAndSP(uptr index, uptr *buffer,
36 uptr *sp) const {
37 UNIMPLEMENTED();
38 }
39
40 // The buffer in GetRegistersAndSP should be at least this big.
41 virtual uptr RegisterCount() const { UNIMPLEMENTED(); }
42 virtual uptr ThreadCount() const { UNIMPLEMENTED(); }
43 virtual tid_t GetThreadID(uptr index) const { UNIMPLEMENTED(); }
44
45 private:
46 // Prohibit copy and assign.
47 SuspendedThreadsList(const SuspendedThreadsList&);
48 void operator=(const SuspendedThreadsList&);
49};
50
51typedef void (*StopTheWorldCallback)(
52 const SuspendedThreadsList &suspended_threads_list,
53 void *argument);
54
55// Suspend all threads in the current process and run the callback on the list
56// of suspended threads. This function will resume the threads before returning.
57// The callback should not call any libc functions. The callback must not call
58// exit() nor _exit() and instead return to the caller.
59// This function should NOT be called from multiple threads simultaneously.
60void StopTheWorld(StopTheWorldCallback callback, void *argument);
61
62} // namespace __sanitizer
63
64#endif // SANITIZER_STOPTHEWORLD_H
lib/tsan/sanitizer_common/sanitizer_stoptheworld_fuchsia.cpp created+42
...@@ -0,0 +1,42 @@
1//===-- sanitizer_stoptheworld_fuchsia.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_FUCHSIA
16
17#include <zircon/sanitizer.h>
18
19#include "sanitizer_stoptheworld.h"
20
21namespace __sanitizer {
22
23// The Fuchsia implementation stops the world but doesn't offer a real
24// SuspendedThreadsList argument. This is enough for ASan's use case,
25// and LSan does not use this API on Fuchsia.
26void StopTheWorld(StopTheWorldCallback callback, void *argument) {
27 struct Params {
28 StopTheWorldCallback callback;
29 void *argument;
30 } params = {callback, argument};
31 __sanitizer_memory_snapshot(
32 nullptr, nullptr, nullptr, nullptr,
33 [](zx_status_t, void *data) {
34 auto params = reinterpret_cast<Params *>(data);
35 params->callback({}, params->argument);
36 },
37 &params);
38}
39
40} // namespace __sanitizer
41
42#endif // SANITIZER_FUCHSIA
lib/tsan/sanitizer_common/sanitizer_stoptheworld_mac.cpp created+182
...@@ -0,0 +1,182 @@
1//===-- sanitizer_stoptheworld_mac.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_MAC && (defined(__x86_64__) || defined(__aarch64__) || \
16 defined(__i386))
17
18#include <mach/mach.h>
19#include <mach/thread_info.h>
20#include <pthread.h>
21
22#include "sanitizer_stoptheworld.h"
23
24namespace __sanitizer {
25typedef struct {
26 tid_t tid;
27 thread_t thread;
28} SuspendedThreadInfo;
29
30class SuspendedThreadsListMac : public SuspendedThreadsList {
31 public:
32 SuspendedThreadsListMac() : threads_(1024) {}
33
34 tid_t GetThreadID(uptr index) const;
35 thread_t GetThread(uptr index) const;
36 uptr ThreadCount() const;
37 bool ContainsThread(thread_t thread) const;
38 void Append(thread_t thread);
39
40 PtraceRegistersStatus GetRegistersAndSP(uptr index, uptr *buffer,
41 uptr *sp) const;
42 uptr RegisterCount() const;
43
44 private:
45 InternalMmapVector<SuspendedThreadInfo> threads_;
46};
47
48struct RunThreadArgs {
49 StopTheWorldCallback callback;
50 void *argument;
51};
52
53void *RunThread(void *arg) {
54 struct RunThreadArgs *run_args = (struct RunThreadArgs *)arg;
55 SuspendedThreadsListMac suspended_threads_list;
56
57 thread_array_t threads;
58 mach_msg_type_number_t num_threads;
59 kern_return_t err = task_threads(mach_task_self(), &threads, &num_threads);
60 if (err != KERN_SUCCESS) {
61 VReport(1, "Failed to get threads for task (errno %d).\n", err);
62 return nullptr;
63 }
64
65 thread_t thread_self = mach_thread_self();
66 for (unsigned int i = 0; i < num_threads; ++i) {
67 if (threads[i] == thread_self) continue;
68
69 thread_suspend(threads[i]);
70 suspended_threads_list.Append(threads[i]);
71 }
72
73 run_args->callback(suspended_threads_list, run_args->argument);
74
75 uptr num_suspended = suspended_threads_list.ThreadCount();
76 for (unsigned int i = 0; i < num_suspended; ++i) {
77 thread_resume(suspended_threads_list.GetThread(i));
78 }
79 return nullptr;
80}
81
82void StopTheWorld(StopTheWorldCallback callback, void *argument) {
83 struct RunThreadArgs arg = {callback, argument};
84 pthread_t run_thread = (pthread_t)internal_start_thread(RunThread, &arg);
85 internal_join_thread(run_thread);
86}
87
88#if defined(__x86_64__)
89typedef x86_thread_state64_t regs_struct;
90
91#define SP_REG __rsp
92
93#elif defined(__aarch64__)
94typedef arm_thread_state64_t regs_struct;
95
96# if __DARWIN_UNIX03
97# define SP_REG __sp
98# else
99# define SP_REG sp
100# endif
101
102#elif defined(__i386)
103typedef x86_thread_state32_t regs_struct;
104
105#define SP_REG __esp
106
107#else
108#error "Unsupported architecture"
109#endif
110
111tid_t SuspendedThreadsListMac::GetThreadID(uptr index) const {
112 CHECK_LT(index, threads_.size());
113 return threads_[index].tid;
114}
115
116thread_t SuspendedThreadsListMac::GetThread(uptr index) const {
117 CHECK_LT(index, threads_.size());
118 return threads_[index].thread;
119}
120
121uptr SuspendedThreadsListMac::ThreadCount() const {
122 return threads_.size();
123}
124
125bool SuspendedThreadsListMac::ContainsThread(thread_t thread) const {
126 for (uptr i = 0; i < threads_.size(); i++) {
127 if (threads_[i].thread == thread) return true;
128 }
129 return false;
130}
131
132void SuspendedThreadsListMac::Append(thread_t thread) {
133 thread_identifier_info_data_t info;
134 mach_msg_type_number_t info_count = THREAD_IDENTIFIER_INFO_COUNT;
135 kern_return_t err = thread_info(thread, THREAD_IDENTIFIER_INFO,
136 (thread_info_t)&info, &info_count);
137 if (err != KERN_SUCCESS) {
138 VReport(1, "Error - unable to get thread ident for a thread\n");
139 return;
140 }
141 threads_.push_back({info.thread_id, thread});
142}
143
144PtraceRegistersStatus SuspendedThreadsListMac::GetRegistersAndSP(
145 uptr index, uptr *buffer, uptr *sp) const {
146 thread_t thread = GetThread(index);
147 regs_struct regs;
148 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,
151 &reg_count);
152 if (err != KERN_SUCCESS) {
153 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,
156 // MIG_ARRAY_TOO_LARGE, means that the state is too large, but it's
157 // still safe to proceed.
158 return err == KERN_INVALID_ARGUMENT ? REGISTERS_UNAVAILABLE_FATAL
159 : REGISTERS_UNAVAILABLE;
160 }
161
162 internal_memcpy(buffer, &regs, sizeof(regs));
163#if defined(__aarch64__) && defined(arm_thread_state64_get_sp)
164 *sp = arm_thread_state64_get_sp(regs);
165#else
166 *sp = regs.SP_REG;
167#endif
168
169 // On x86_64 and aarch64, we must account for the stack redzone, which is 128
170 // bytes.
171 if (SANITIZER_WORDSIZE == 64) *sp -= 128;
172
173 return REGISTERS_AVAILABLE;
174}
175
176uptr SuspendedThreadsListMac::RegisterCount() const {
177 return MACHINE_THREAD_STATE_COUNT;
178}
179} // namespace __sanitizer
180
181#endif // SANITIZER_MAC && (defined(__x86_64__) || defined(__aarch64__)) ||
182 // defined(__i386))
lib/tsan/sanitizer_common/sanitizer_suppressions.cpp created+181
...@@ -0,0 +1,181 @@
1//===-- sanitizer_suppressions.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// Suppression parsing/matching code.
10//
11//===----------------------------------------------------------------------===//
12
13#include "sanitizer_suppressions.h"
14
15#include "sanitizer_allocator_internal.h"
16#include "sanitizer_common.h"
17#include "sanitizer_flags.h"
18#include "sanitizer_file.h"
19#include "sanitizer_libc.h"
20#include "sanitizer_placement_new.h"
21
22namespace __sanitizer {
23
24SuppressionContext::SuppressionContext(const char *suppression_types[],
25 int suppression_types_num)
26 : suppression_types_(suppression_types),
27 suppression_types_num_(suppression_types_num),
28 can_parse_(true) {
29 CHECK_LE(suppression_types_num_, kMaxSuppressionTypes);
30 internal_memset(has_suppression_type_, 0, suppression_types_num_);
31}
32
33#if !SANITIZER_FUCHSIA
34static bool GetPathAssumingFileIsRelativeToExec(const char *file_path,
35 /*out*/char *new_file_path,
36 uptr new_file_path_size) {
37 InternalScopedString exec(kMaxPathLength);
38 if (ReadBinaryNameCached(exec.data(), exec.size())) {
39 const char *file_name_pos = StripModuleName(exec.data());
40 uptr path_to_exec_len = file_name_pos - exec.data();
41 internal_strncat(new_file_path, exec.data(),
42 Min(path_to_exec_len, new_file_path_size - 1));
43 internal_strncat(new_file_path, file_path,
44 new_file_path_size - internal_strlen(new_file_path) - 1);
45 return true;
46 }
47 return false;
48}
49
50static const char *FindFile(const char *file_path,
51 /*out*/char *new_file_path,
52 uptr new_file_path_size) {
53 // If we cannot find the file, check if its location is relative to
54 // the location of the executable.
55 if (!FileExists(file_path) && !IsAbsolutePath(file_path) &&
56 GetPathAssumingFileIsRelativeToExec(file_path, new_file_path,
57 new_file_path_size)) {
58 return new_file_path;
59 }
60 return file_path;
61}
62#else
63static const char *FindFile(const char *file_path, char *, uptr) {
64 return file_path;
65}
66#endif
67
68void SuppressionContext::ParseFromFile(const char *filename) {
69 if (filename[0] == '\0')
70 return;
71
72 InternalScopedString new_file_path(kMaxPathLength);
73 filename = FindFile(filename, new_file_path.data(), new_file_path.size());
74
75 // Read the file.
76 VPrintf(1, "%s: reading suppressions file at %s\n",
77 SanitizerToolName, filename);
78 char *file_contents;
79 uptr buffer_size;
80 uptr contents_size;
81 if (!ReadFileToBuffer(filename, &file_contents, &buffer_size,
82 &contents_size)) {
83 Printf("%s: failed to read suppressions file '%s'\n", SanitizerToolName,
84 filename);
85 Die();
86 }
87
88 Parse(file_contents);
89}
90
91bool SuppressionContext::Match(const char *str, const char *type,
92 Suppression **s) {
93 can_parse_ = false;
94 if (!HasSuppressionType(type))
95 return false;
96 for (uptr i = 0; i < suppressions_.size(); i++) {
97 Suppression &cur = suppressions_[i];
98 if (0 == internal_strcmp(cur.type, type) && TemplateMatch(cur.templ, str)) {
99 *s = &cur;
100 return true;
101 }
102 }
103 return false;
104}
105
106static const char *StripPrefix(const char *str, const char *prefix) {
107 while (*str && *str == *prefix) {
108 str++;
109 prefix++;
110 }
111 if (!*prefix)
112 return str;
113 return 0;
114}
115
116void SuppressionContext::Parse(const char *str) {
117 // Context must not mutate once Match has been called.
118 CHECK(can_parse_);
119 const char *line = str;
120 while (line) {
121 while (line[0] == ' ' || line[0] == '\t')
122 line++;
123 const char *end = internal_strchr(line, '\n');
124 if (end == 0)
125 end = line + internal_strlen(line);
126 if (line != end && line[0] != '#') {
127 const char *end2 = end;
128 while (line != end2 &&
129 (end2[-1] == ' ' || end2[-1] == '\t' || end2[-1] == '\r'))
130 end2--;
131 int type;
132 for (type = 0; type < suppression_types_num_; type++) {
133 const char *next_char = StripPrefix(line, suppression_types_[type]);
134 if (next_char && *next_char == ':') {
135 line = ++next_char;
136 break;
137 }
138 }
139 if (type == suppression_types_num_) {
140 Printf("%s: failed to parse suppressions\n", SanitizerToolName);
141 Die();
142 }
143 Suppression s;
144 s.type = suppression_types_[type];
145 s.templ = (char*)InternalAlloc(end2 - line + 1);
146 internal_memcpy(s.templ, line, end2 - line);
147 s.templ[end2 - line] = 0;
148 suppressions_.push_back(s);
149 has_suppression_type_[type] = true;
150 }
151 if (end[0] == 0)
152 break;
153 line = end + 1;
154 }
155}
156
157uptr SuppressionContext::SuppressionCount() const {
158 return suppressions_.size();
159}
160
161bool SuppressionContext::HasSuppressionType(const char *type) const {
162 for (int i = 0; i < suppression_types_num_; i++) {
163 if (0 == internal_strcmp(type, suppression_types_[i]))
164 return has_suppression_type_[i];
165 }
166 return false;
167}
168
169const Suppression *SuppressionContext::SuppressionAt(uptr i) const {
170 CHECK_LT(i, suppressions_.size());
171 return &suppressions_[i];
172}
173
174void SuppressionContext::GetMatched(
175 InternalMmapVector<Suppression *> *matched) {
176 for (uptr i = 0; i < suppressions_.size(); i++)
177 if (atomic_load_relaxed(&suppressions_[i].hit_count))
178 matched->push_back(&suppressions_[i]);
179}
180
181} // namespace __sanitizer
lib/tsan/sanitizer_common/sanitizer_suppressions.h created+56
...@@ -0,0 +1,56 @@
1//===-- sanitizer_suppressions.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// Suppression parsing/matching code.
10//
11//===----------------------------------------------------------------------===//
12#ifndef SANITIZER_SUPPRESSIONS_H
13#define SANITIZER_SUPPRESSIONS_H
14
15#include "sanitizer_common.h"
16#include "sanitizer_atomic.h"
17#include "sanitizer_internal_defs.h"
18
19namespace __sanitizer {
20
21struct Suppression {
22 Suppression() { internal_memset(this, 0, sizeof(*this)); }
23 const char *type;
24 char *templ;
25 atomic_uint32_t hit_count;
26 uptr weight;
27};
28
29class SuppressionContext {
30 public:
31 // Create new SuppressionContext capable of parsing given suppression types.
32 SuppressionContext(const char *supprression_types[],
33 int suppression_types_num);
34
35 void ParseFromFile(const char *filename);
36 void Parse(const char *str);
37
38 bool Match(const char *str, const char *type, Suppression **s);
39 uptr SuppressionCount() const;
40 bool HasSuppressionType(const char *type) const;
41 const Suppression *SuppressionAt(uptr i) const;
42 void GetMatched(InternalMmapVector<Suppression *> *matched);
43
44 private:
45 static const int kMaxSuppressionTypes = 64;
46 const char **const suppression_types_;
47 const int suppression_types_num_;
48
49 InternalMmapVector<Suppression> suppressions_;
50 bool has_suppression_type_[kMaxSuppressionTypes];
51 bool can_parse_;
52};
53
54} // namespace __sanitizer
55
56#endif // SANITIZER_SUPPRESSIONS_H
lib/tsan/sanitizer_common/sanitizer_symbolizer.h created+223
...@@ -0,0 +1,223 @@
1//===-- sanitizer_symbolizer.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// Symbolizer is used by sanitizers to map instruction address to a location in
10// source code at run-time. Symbolizer either uses __sanitizer_symbolize_*
11// defined in the program, or (if they are missing) tries to find and
12// launch "llvm-symbolizer" commandline tool in a separate process and
13// communicate with it.
14//
15// Generally we should try to avoid calling system library functions during
16// symbolization (and use their replacements from sanitizer_libc.h instead).
17//===----------------------------------------------------------------------===//
18#ifndef SANITIZER_SYMBOLIZER_H
19#define SANITIZER_SYMBOLIZER_H
20
21#include "sanitizer_common.h"
22#include "sanitizer_mutex.h"
23#include "sanitizer_vector.h"
24
25namespace __sanitizer {
26
27struct AddressInfo {
28 // Owns all the string members. Storage for them is
29 // (de)allocated using sanitizer internal allocator.
30 uptr address;
31
32 char *module;
33 uptr module_offset;
34 ModuleArch module_arch;
35
36 static const uptr kUnknown = ~(uptr)0;
37 char *function;
38 uptr function_offset;
39
40 char *file;
41 int line;
42 int column;
43
44 AddressInfo();
45 // Deletes all strings and resets all fields.
46 void Clear();
47 void FillModuleInfo(const char *mod_name, uptr mod_offset, ModuleArch arch);
48};
49
50// Linked list of symbolized frames (each frame is described by AddressInfo).
51struct SymbolizedStack {
52 SymbolizedStack *next;
53 AddressInfo info;
54 static SymbolizedStack *New(uptr addr);
55 // Deletes current, and all subsequent frames in the linked list.
56 // The object cannot be accessed after the call to this function.
57 void ClearAll();
58
59 private:
60 SymbolizedStack();
61};
62
63// For now, DataInfo is used to describe global variable.
64struct DataInfo {
65 // Owns all the string members. Storage for them is
66 // (de)allocated using sanitizer internal allocator.
67 char *module;
68 uptr module_offset;
69 ModuleArch module_arch;
70
71 char *file;
72 uptr line;
73 char *name;
74 uptr start;
75 uptr size;
76
77 DataInfo();
78 void Clear();
79};
80
81struct LocalInfo {
82 char *function_name = nullptr;
83 char *name = nullptr;
84 char *decl_file = nullptr;
85 unsigned decl_line = 0;
86
87 bool has_frame_offset = false;
88 bool has_size = false;
89 bool has_tag_offset = false;
90
91 sptr frame_offset;
92 uptr size;
93 uptr tag_offset;
94
95 void Clear();
96};
97
98struct FrameInfo {
99 char *module;
100 uptr module_offset;
101 ModuleArch module_arch;
102
103 InternalMmapVector<LocalInfo> locals;
104 void Clear();
105};
106
107class SymbolizerTool;
108
109class Symbolizer final {
110 public:
111 /// Initialize and return platform-specific implementation of symbolizer
112 /// (if it wasn't already initialized).
113 static Symbolizer *GetOrInit();
114 static void LateInitialize();
115 // Returns a list of symbolized frames for a given address (containing
116 // all inlined functions, if necessary).
117 SymbolizedStack *SymbolizePC(uptr address);
118 bool SymbolizeData(uptr address, DataInfo *info);
119 bool SymbolizeFrame(uptr address, FrameInfo *info);
120
121 // The module names Symbolizer returns are stable and unique for every given
122 // module. It is safe to store and compare them as pointers.
123 bool GetModuleNameAndOffsetForPC(uptr pc, const char **module_name,
124 uptr *module_address);
125 const char *GetModuleNameForPc(uptr pc) {
126 const char *module_name = nullptr;
127 uptr unused;
128 if (GetModuleNameAndOffsetForPC(pc, &module_name, &unused))
129 return module_name;
130 return nullptr;
131 }
132
133 // Release internal caches (if any).
134 void Flush();
135 // Attempts to demangle the provided C++ mangled name.
136 const char *Demangle(const char *name);
137
138 // Allow user to install hooks that would be called before/after Symbolizer
139 // does the actual file/line info fetching. Specific sanitizers may need this
140 // to distinguish system library calls made in user code from calls made
141 // during in-process symbolization.
142 typedef void (*StartSymbolizationHook)();
143 typedef void (*EndSymbolizationHook)();
144 // May be called at most once.
145 void AddHooks(StartSymbolizationHook start_hook,
146 EndSymbolizationHook end_hook);
147
148 void RefreshModules();
149 const LoadedModule *FindModuleForAddress(uptr address);
150
151 void InvalidateModuleList();
152
153 private:
154 // GetModuleNameAndOffsetForPC has to return a string to the caller.
155 // Since the corresponding module might get unloaded later, we should create
156 // our owned copies of the strings that we can safely return.
157 // ModuleNameOwner does not provide any synchronization, thus calls to
158 // its method should be protected by |mu_|.
159 class ModuleNameOwner {
160 public:
161 explicit ModuleNameOwner(BlockingMutex *synchronized_by)
162 : last_match_(nullptr), mu_(synchronized_by) {
163 storage_.reserve(kInitialCapacity);
164 }
165 const char *GetOwnedCopy(const char *str);
166
167 private:
168 static const uptr kInitialCapacity = 1000;
169 InternalMmapVector<const char*> storage_;
170 const char *last_match_;
171
172 BlockingMutex *mu_;
173 } module_names_;
174
175 /// Platform-specific function for creating a Symbolizer object.
176 static Symbolizer *PlatformInit();
177
178 bool FindModuleNameAndOffsetForAddress(uptr address, const char **module_name,
179 uptr *module_offset,
180 ModuleArch *module_arch);
181 ListOfModules modules_;
182 ListOfModules fallback_modules_;
183 // If stale, need to reload the modules before looking up addresses.
184 bool modules_fresh_;
185
186 // Platform-specific default demangler, must not return nullptr.
187 const char *PlatformDemangle(const char *name);
188
189 static Symbolizer *symbolizer_;
190 static StaticSpinMutex init_mu_;
191
192 // Mutex locked from public methods of |Symbolizer|, so that the internals
193 // (including individual symbolizer tools and platform-specific methods) are
194 // always synchronized.
195 BlockingMutex mu_;
196
197 IntrusiveList<SymbolizerTool> tools_;
198
199 explicit Symbolizer(IntrusiveList<SymbolizerTool> tools);
200
201 static LowLevelAllocator symbolizer_allocator_;
202
203 StartSymbolizationHook start_hook_;
204 EndSymbolizationHook end_hook_;
205 class SymbolizerScope {
206 public:
207 explicit SymbolizerScope(const Symbolizer *sym);
208 ~SymbolizerScope();
209 private:
210 const Symbolizer *sym_;
211 };
212
213 // Calls `LateInitialize()` on all items in `tools_`.
214 void LateInitializeTools();
215};
216
217#ifdef SANITIZER_WINDOWS
218void InitializeDbgHelpIfNeeded();
219#endif
220
221} // namespace __sanitizer
222
223#endif // SANITIZER_SYMBOLIZER_H
lib/tsan/sanitizer_common/sanitizer_symbolizer_fuchsia.h created+42
...@@ -0,0 +1,42 @@
1//===-- sanitizer_symbolizer_fuchsia.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 shared between various sanitizers' runtime libraries.
10//
11// Define Fuchsia's string formats and limits for the markup symbolizer.
12//===----------------------------------------------------------------------===//
13#ifndef SANITIZER_SYMBOLIZER_FUCHSIA_H
14#define SANITIZER_SYMBOLIZER_FUCHSIA_H
15
16#include "sanitizer_internal_defs.h"
17
18namespace __sanitizer {
19
20// See the spec at:
21// https://fuchsia.googlesource.com/zircon/+/master/docs/symbolizer_markup.md
22
23// This is used by UBSan for type names, and by ASan for global variable names.
24constexpr const char *kFormatDemangle = "{{{symbol:%s}}}";
25constexpr uptr kFormatDemangleMax = 1024; // Arbitrary.
26
27// Function name or equivalent from PC location.
28constexpr const char *kFormatFunction = "{{{pc:%p}}}";
29constexpr uptr kFormatFunctionMax = 64; // More than big enough for 64-bit hex.
30
31// Global variable name or equivalent from data memory address.
32constexpr const char *kFormatData = "{{{data:%p}}}";
33
34// One frame in a backtrace (printed on a line by itself).
35constexpr const char *kFormatFrame = "{{{bt:%u:%p}}}";
36
37// Dump trigger element.
38#define FORMAT_DUMPFILE "{{{dumpfile:%s:%s}}}"
39
40} // namespace __sanitizer
41
42#endif // SANITIZER_SYMBOLIZER_FUCHSIA_H
lib/tsan/sanitizer_common/sanitizer_symbolizer_internal.h created+165
...@@ -0,0 +1,165 @@
1//===-- sanitizer_symbolizer_internal.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// Header for internal classes and functions to be used by implementations of
10// symbolizers.
11//
12//===----------------------------------------------------------------------===//
13#ifndef SANITIZER_SYMBOLIZER_INTERNAL_H
14#define SANITIZER_SYMBOLIZER_INTERNAL_H
15
16#include "sanitizer_symbolizer.h"
17#include "sanitizer_file.h"
18#include "sanitizer_vector.h"
19
20namespace __sanitizer {
21
22// Parsing helpers, 'str' is searched for delimiter(s) and a string or uptr
23// is extracted. When extracting a string, a newly allocated (using
24// InternalAlloc) and null-terminataed buffer is returned. They return a pointer
25// to the next characted after the found delimiter.
26const char *ExtractToken(const char *str, const char *delims, char **result);
27const char *ExtractInt(const char *str, const char *delims, int *result);
28const char *ExtractUptr(const char *str, const char *delims, uptr *result);
29const char *ExtractTokenUpToDelimiter(const char *str, const char *delimiter,
30 char **result);
31
32const char *DemangleSwiftAndCXX(const char *name);
33
34// SymbolizerTool is an interface that is implemented by individual "tools"
35// that can perform symbolication (external llvm-symbolizer, libbacktrace,
36// Windows DbgHelp symbolizer, etc.).
37class SymbolizerTool {
38 public:
39 // The main |Symbolizer| class implements a "fallback chain" of symbolizer
40 // tools. In a request to symbolize an address, if one tool returns false,
41 // the next tool in the chain will be tried.
42 SymbolizerTool *next;
43
44 SymbolizerTool() : next(nullptr) { }
45
46 // Can't declare pure virtual functions in sanitizer runtimes:
47 // __cxa_pure_virtual might be unavailable.
48
49 // The |stack| parameter is inout. It is pre-filled with the address,
50 // module base and module offset values and is to be used to construct
51 // other stack frames.
52 virtual bool SymbolizePC(uptr addr, SymbolizedStack *stack) {
53 UNIMPLEMENTED();
54 }
55
56 // The |info| parameter is inout. It is pre-filled with the module base
57 // and module offset values.
58 virtual bool SymbolizeData(uptr addr, DataInfo *info) {
59 UNIMPLEMENTED();
60 }
61
62 virtual bool SymbolizeFrame(uptr addr, FrameInfo *info) {
63 return false;
64 }
65
66 virtual void Flush() {}
67
68 // Return nullptr to fallback to the default platform-specific demangler.
69 virtual const char *Demangle(const char *name) {
70 return nullptr;
71 }
72
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};
78
79// SymbolizerProcess encapsulates communication between the tool and
80// external symbolizer program, running in a different subprocess.
81// SymbolizerProcess may not be used from two threads simultaneously.
82class SymbolizerProcess {
83 public:
84 explicit SymbolizerProcess(const char *path, bool use_posix_spawn = false);
85 const char *SendCommand(const char *command);
86
87 protected:
88 /// The maximum number of arguments required to invoke a tool process.
89 static const unsigned kArgVMax = 6;
90
91 // Customizable by subclasses.
92 virtual bool StartSymbolizerSubprocess();
93 virtual bool ReadFromSymbolizer(char *buffer, uptr max_length);
94 // Return the environment to run the symbolizer in.
95 virtual char **GetEnvP() { return GetEnviron(); }
96
97 private:
98 virtual bool ReachedEndOfOutput(const char *buffer, uptr length) const {
99 UNIMPLEMENTED();
100 }
101
102 /// Fill in an argv array to invoke the child process.
103 virtual void GetArgV(const char *path_to_binary,
104 const char *(&argv)[kArgVMax]) const {
105 UNIMPLEMENTED();
106 }
107
108 bool Restart();
109 const char *SendCommandImpl(const char *command);
110 bool WriteToSymbolizer(const char *buffer, uptr length);
111
112 const char *path_;
113 fd_t input_fd_;
114 fd_t output_fd_;
115
116 static const uptr kBufferSize = 16 * 1024;
117 char buffer_[kBufferSize];
118
119 static const uptr kMaxTimesRestarted = 5;
120 static const int kSymbolizerStartupTimeMillis = 10;
121 uptr times_restarted_;
122 bool failed_to_start_;
123 bool reported_invalid_path_;
124 bool use_posix_spawn_;
125};
126
127class LLVMSymbolizerProcess;
128
129// This tool invokes llvm-symbolizer in a subprocess. It should be as portable
130// as the llvm-symbolizer tool is.
131class LLVMSymbolizer : public SymbolizerTool {
132 public:
133 explicit LLVMSymbolizer(const char *path, LowLevelAllocator *allocator);
134
135 bool SymbolizePC(uptr addr, SymbolizedStack *stack) override;
136 bool SymbolizeData(uptr addr, DataInfo *info) override;
137 bool SymbolizeFrame(uptr addr, FrameInfo *info) override;
138
139 private:
140 const char *FormatAndSendCommand(const char *command_prefix,
141 const char *module_name, uptr module_offset,
142 ModuleArch arch);
143
144 LLVMSymbolizerProcess *symbolizer_process_;
145 static const uptr kBufferSize = 16 * 1024;
146 char buffer_[kBufferSize];
147};
148
149// Parses one or more two-line strings in the following format:
150// <function_name>
151// <file_name>:<line_number>[:<column_number>]
152// Used by LLVMSymbolizer, Addr2LinePool and InternalSymbolizer, since all of
153// them use the same output format. Returns true if any useful debug
154// information was found.
155void ParseSymbolizePCOutput(const char *str, SymbolizedStack *res);
156
157// Parses a two-line string in the following format:
158// <symbol_name>
159// <start_address> <size>
160// Used by LLVMSymbolizer and InternalSymbolizer.
161void ParseSymbolizeDataOutput(const char *str, DataInfo *info);
162
163} // namespace __sanitizer
164
165#endif // SANITIZER_SYMBOLIZER_INTERNAL_H
lib/tsan/sanitizer_common/sanitizer_symbolizer_libbacktrace.h created+49
...@@ -0,0 +1,49 @@
1//===-- sanitizer_symbolizer_libbacktrace.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 AddressSanitizer and ThreadSanitizer
10// run-time libraries.
11// Header for libbacktrace symbolizer.
12//===----------------------------------------------------------------------===//
13#ifndef SANITIZER_SYMBOLIZER_LIBBACKTRACE_H
14#define SANITIZER_SYMBOLIZER_LIBBACKTRACE_H
15
16#include "sanitizer_platform.h"
17#include "sanitizer_common.h"
18#include "sanitizer_allocator_internal.h"
19#include "sanitizer_symbolizer_internal.h"
20
21#ifndef SANITIZER_LIBBACKTRACE
22# define SANITIZER_LIBBACKTRACE 0
23#endif
24
25#ifndef SANITIZER_CP_DEMANGLE
26# define SANITIZER_CP_DEMANGLE 0
27#endif
28
29namespace __sanitizer {
30
31class LibbacktraceSymbolizer : public SymbolizerTool {
32 public:
33 static LibbacktraceSymbolizer *get(LowLevelAllocator *alloc);
34
35 bool SymbolizePC(uptr addr, SymbolizedStack *stack) override;
36
37 bool SymbolizeData(uptr addr, DataInfo *info) override;
38
39 // May return NULL if demangling failed.
40 const char *Demangle(const char *name) override;
41
42 private:
43 explicit LibbacktraceSymbolizer(void *state) : state_(state) {}
44
45 void *state_; // Leaked.
46};
47
48} // namespace __sanitizer
49#endif // SANITIZER_SYMBOLIZER_LIBBACKTRACE_H
lib/tsan/sanitizer_common/sanitizer_symbolizer_mac.h created+48
...@@ -0,0 +1,48 @@
1//===-- sanitizer_symbolizer_mac.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 various sanitizers' runtime libraries.
10//
11// Header for Mac-specific "atos" symbolizer.
12//===----------------------------------------------------------------------===//
13
14#ifndef SANITIZER_SYMBOLIZER_MAC_H
15#define SANITIZER_SYMBOLIZER_MAC_H
16
17#include "sanitizer_platform.h"
18#if SANITIZER_MAC
19
20#include "sanitizer_symbolizer_internal.h"
21
22namespace __sanitizer {
23
24class DlAddrSymbolizer : public SymbolizerTool {
25 public:
26 bool SymbolizePC(uptr addr, SymbolizedStack *stack) override;
27 bool SymbolizeData(uptr addr, DataInfo *info) override;
28};
29
30class AtosSymbolizerProcess;
31
32class AtosSymbolizer : public SymbolizerTool {
33 public:
34 explicit AtosSymbolizer(const char *path, LowLevelAllocator *allocator);
35
36 bool SymbolizePC(uptr addr, SymbolizedStack *stack) override;
37 bool SymbolizeData(uptr addr, DataInfo *info) override;
38 void LateInitialize() override;
39
40 private:
41 AtosSymbolizerProcess *process_;
42};
43
44} // namespace __sanitizer
45
46#endif // SANITIZER_MAC
47
48#endif // SANITIZER_SYMBOLIZER_MAC_H
lib/tsan/sanitizer_common/sanitizer_symbolizer_rtems.h created+40
...@@ -0,0 +1,40 @@
1//===-- sanitizer_symbolizer_rtems.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 shared between various sanitizers' runtime libraries.
10//
11// Define RTEMS's string formats and limits for the markup symbolizer.
12//===----------------------------------------------------------------------===//
13#ifndef SANITIZER_SYMBOLIZER_RTEMS_H
14#define SANITIZER_SYMBOLIZER_RTEMS_H
15
16#include "sanitizer_internal_defs.h"
17
18namespace __sanitizer {
19
20// The Myriad RTEMS symbolizer currently only parses backtrace lines,
21// so use a format that the symbolizer understands. For other
22// markups, keep them the same as the Fuchsia's.
23
24// This is used by UBSan for type names, and by ASan for global variable names.
25constexpr const char *kFormatDemangle = "{{{symbol:%s}}}";
26constexpr uptr kFormatDemangleMax = 1024; // Arbitrary.
27
28// Function name or equivalent from PC location.
29constexpr const char *kFormatFunction = "{{{pc:%p}}}";
30constexpr uptr kFormatFunctionMax = 64; // More than big enough for 64-bit hex.
31
32// Global variable name or equivalent from data memory address.
33constexpr const char *kFormatData = "{{{data:%p}}}";
34
35// One frame in a backtrace (printed on a line by itself).
36constexpr const char *kFormatFrame = " [%u] IP: %p";
37
38} // namespace __sanitizer
39
40#endif // SANITIZER_SYMBOLIZER_RTEMS_H
lib/tsan/sanitizer_common/sanitizer_syscall_generic.inc created+38
...@@ -0,0 +1,38 @@
1//===-- sanitizer_syscall_generic.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// Generic implementations of internal_syscall* and internal_iserror.
10//
11//===----------------------------------------------------------------------===//
12
13// NetBSD uses libc calls directly
14#if !SANITIZER_NETBSD
15
16#if SANITIZER_FREEBSD || SANITIZER_MAC || SANITIZER_OPENBSD || SANITIZER_SOLARIS
17# define SYSCALL(name) SYS_ ## name
18#else
19# define SYSCALL(name) __NR_ ## name
20#endif
21
22#if defined(__x86_64__) && (SANITIZER_FREEBSD || SANITIZER_MAC)
23# define internal_syscall __syscall
24# else
25# define internal_syscall syscall
26#endif
27
28#endif
29
30bool internal_iserror(uptr retval, int *rverrno) {
31 if (retval == (uptr)-1) {
32 if (rverrno)
33 *rverrno = errno;
34 return true;
35 } else {
36 return false;
37 }
38}
lib/tsan/sanitizer_common/sanitizer_syscall_linux_aarch64.inc created+137
...@@ -0,0 +1,137 @@
1//===-- sanitizer_syscall_linux_aarch64.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// Implementations of internal_syscall and internal_iserror for Linux/aarch64.
10//
11//===----------------------------------------------------------------------===//
12
13#define SYSCALL(name) __NR_ ## name
14
15static uptr __internal_syscall(u64 nr) {
16 register u64 x8 asm("x8") = nr;
17 register u64 x0 asm("x0");
18 asm volatile("svc 0"
19 : "=r"(x0)
20 : "r"(x8)
21 : "memory", "cc");
22 return x0;
23}
24#define __internal_syscall0(n) \
25 (__internal_syscall)(n)
26
27static uptr __internal_syscall(u64 nr, u64 arg1) {
28 register u64 x8 asm("x8") = nr;
29 register u64 x0 asm("x0") = arg1;
30 asm volatile("svc 0"
31 : "=r"(x0)
32 : "r"(x8), "0"(x0)
33 : "memory", "cc");
34 return x0;
35}
36#define __internal_syscall1(n, a1) \
37 (__internal_syscall)(n, (u64)(a1))
38
39static uptr __internal_syscall(u64 nr, u64 arg1, long arg2) {
40 register u64 x8 asm("x8") = nr;
41 register u64 x0 asm("x0") = arg1;
42 register u64 x1 asm("x1") = arg2;
43 asm volatile("svc 0"
44 : "=r"(x0)
45 : "r"(x8), "0"(x0), "r"(x1)
46 : "memory", "cc");
47 return x0;
48}
49#define __internal_syscall2(n, a1, a2) \
50 (__internal_syscall)(n, (u64)(a1), (long)(a2))
51
52static uptr __internal_syscall(u64 nr, u64 arg1, long arg2, long arg3) {
53 register u64 x8 asm("x8") = nr;
54 register u64 x0 asm("x0") = arg1;
55 register u64 x1 asm("x1") = arg2;
56 register u64 x2 asm("x2") = arg3;
57 asm volatile("svc 0"
58 : "=r"(x0)
59 : "r"(x8), "0"(x0), "r"(x1), "r"(x2)
60 : "memory", "cc");
61 return x0;
62}
63#define __internal_syscall3(n, a1, a2, a3) \
64 (__internal_syscall)(n, (u64)(a1), (long)(a2), (long)(a3))
65
66static uptr __internal_syscall(u64 nr, u64 arg1, long arg2, long arg3,
67 u64 arg4) {
68 register u64 x8 asm("x8") = nr;
69 register u64 x0 asm("x0") = arg1;
70 register u64 x1 asm("x1") = arg2;
71 register u64 x2 asm("x2") = arg3;
72 register u64 x3 asm("x3") = arg4;
73 asm volatile("svc 0"
74 : "=r"(x0)
75 : "r"(x8), "0"(x0), "r"(x1), "r"(x2), "r"(x3)
76 : "memory", "cc");
77 return x0;
78}
79#define __internal_syscall4(n, a1, a2, a3, a4) \
80 (__internal_syscall)(n, (u64)(a1), (long)(a2), (long)(a3), (long)(a4))
81
82static uptr __internal_syscall(u64 nr, u64 arg1, long arg2, long arg3,
83 u64 arg4, long arg5) {
84 register u64 x8 asm("x8") = nr;
85 register u64 x0 asm("x0") = arg1;
86 register u64 x1 asm("x1") = arg2;
87 register u64 x2 asm("x2") = arg3;
88 register u64 x3 asm("x3") = arg4;
89 register u64 x4 asm("x4") = arg5;
90 asm volatile("svc 0"
91 : "=r"(x0)
92 : "r"(x8), "0"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x4)
93 : "memory", "cc");
94 return x0;
95}
96#define __internal_syscall5(n, a1, a2, a3, a4, a5) \
97 (__internal_syscall)(n, (u64)(a1), (long)(a2), (long)(a3), (long)(a4), \
98 (u64)(a5))
99
100static uptr __internal_syscall(u64 nr, u64 arg1, long arg2, long arg3,
101 u64 arg4, long arg5, long arg6) {
102 register u64 x8 asm("x8") = nr;
103 register u64 x0 asm("x0") = arg1;
104 register u64 x1 asm("x1") = arg2;
105 register u64 x2 asm("x2") = arg3;
106 register u64 x3 asm("x3") = arg4;
107 register u64 x4 asm("x4") = arg5;
108 register u64 x5 asm("x5") = arg6;
109 asm volatile("svc 0"
110 : "=r"(x0)
111 : "r"(x8), "0"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x4), "r"(x5)
112 : "memory", "cc");
113 return x0;
114}
115#define __internal_syscall6(n, a1, a2, a3, a4, a5, a6) \
116 (__internal_syscall)(n, (u64)(a1), (long)(a2), (long)(a3), (long)(a4), \
117 (u64)(a5), (long)(a6))
118
119#define __SYSCALL_NARGS_X(a1, a2, a3, a4, a5, a6, a7, a8, n, ...) n
120#define __SYSCALL_NARGS(...) \
121 __SYSCALL_NARGS_X(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0, )
122#define __SYSCALL_CONCAT_X(a, b) a##b
123#define __SYSCALL_CONCAT(a, b) __SYSCALL_CONCAT_X(a, b)
124#define __SYSCALL_DISP(b, ...) \
125 __SYSCALL_CONCAT(b, __SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__)
126
127#define internal_syscall(...) __SYSCALL_DISP(__internal_syscall, __VA_ARGS__)
128
129// Helper function used to avoid cobbler errno.
130bool internal_iserror(uptr retval, int *rverrno) {
131 if (retval >= (uptr)-4095) {
132 if (rverrno)
133 *rverrno = -retval;
134 return true;
135 }
136 return false;
137}
lib/tsan/sanitizer_common/sanitizer_syscall_linux_arm.inc created+137
...@@ -0,0 +1,137 @@
1//===-- sanitizer_syscall_linux_arm.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// Implementations of internal_syscall and internal_iserror for Linux/arm.
10//
11//===----------------------------------------------------------------------===//
12
13#define SYSCALL(name) __NR_ ## name
14
15static uptr __internal_syscall(u32 nr) {
16 register u32 r8 asm("r7") = nr;
17 register u32 r0 asm("r0");
18 asm volatile("swi #0"
19 : "=r"(r0)
20 : "r"(r8)
21 : "memory", "cc");
22 return r0;
23}
24#define __internal_syscall0(n) \
25 (__internal_syscall)(n)
26
27static uptr __internal_syscall(u32 nr, u32 arg1) {
28 register u32 r8 asm("r7") = nr;
29 register u32 r0 asm("r0") = arg1;
30 asm volatile("swi #0"
31 : "=r"(r0)
32 : "r"(r8), "0"(r0)
33 : "memory", "cc");
34 return r0;
35}
36#define __internal_syscall1(n, a1) \
37 (__internal_syscall)(n, (u32)(a1))
38
39static uptr __internal_syscall(u32 nr, u32 arg1, long arg2) {
40 register u32 r8 asm("r7") = nr;
41 register u32 r0 asm("r0") = arg1;
42 register u32 r1 asm("r1") = arg2;
43 asm volatile("swi #0"
44 : "=r"(r0)
45 : "r"(r8), "0"(r0), "r"(r1)
46 : "memory", "cc");
47 return r0;
48}
49#define __internal_syscall2(n, a1, a2) \
50 (__internal_syscall)(n, (u32)(a1), (long)(a2))
51
52static uptr __internal_syscall(u32 nr, u32 arg1, long arg2, long arg3) {
53 register u32 r8 asm("r7") = nr;
54 register u32 r0 asm("r0") = arg1;
55 register u32 r1 asm("r1") = arg2;
56 register u32 r2 asm("r2") = arg3;
57 asm volatile("swi #0"
58 : "=r"(r0)
59 : "r"(r8), "0"(r0), "r"(r1), "r"(r2)
60 : "memory", "cc");
61 return r0;
62}
63#define __internal_syscall3(n, a1, a2, a3) \
64 (__internal_syscall)(n, (u32)(a1), (long)(a2), (long)(a3))
65
66static uptr __internal_syscall(u32 nr, u32 arg1, long arg2, long arg3,
67 u32 arg4) {
68 register u32 r8 asm("r7") = nr;
69 register u32 r0 asm("r0") = arg1;
70 register u32 r1 asm("r1") = arg2;
71 register u32 r2 asm("r2") = arg3;
72 register u32 r3 asm("r3") = arg4;
73 asm volatile("swi #0"
74 : "=r"(r0)
75 : "r"(r8), "0"(r0), "r"(r1), "r"(r2), "r"(r3)
76 : "memory", "cc");
77 return r0;
78}
79#define __internal_syscall4(n, a1, a2, a3, a4) \
80 (__internal_syscall)(n, (u32)(a1), (long)(a2), (long)(a3), (long)(a4))
81
82static uptr __internal_syscall(u32 nr, u32 arg1, long arg2, long arg3,
83 u32 arg4, long arg5) {
84 register u32 r8 asm("r7") = nr;
85 register u32 r0 asm("r0") = arg1;
86 register u32 r1 asm("r1") = arg2;
87 register u32 r2 asm("r2") = arg3;
88 register u32 r3 asm("r3") = arg4;
89 register u32 r4 asm("r4") = arg5;
90 asm volatile("swi #0"
91 : "=r"(r0)
92 : "r"(r8), "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4)
93 : "memory", "cc");
94 return r0;
95}
96#define __internal_syscall5(n, a1, a2, a3, a4, a5) \
97 (__internal_syscall)(n, (u32)(a1), (long)(a2), (long)(a3), (long)(a4), \
98 (u32)(a5))
99
100static uptr __internal_syscall(u32 nr, u32 arg1, long arg2, long arg3,
101 u32 arg4, long arg5, long arg6) {
102 register u32 r8 asm("r7") = nr;
103 register u32 r0 asm("r0") = arg1;
104 register u32 r1 asm("r1") = arg2;
105 register u32 r2 asm("r2") = arg3;
106 register u32 r3 asm("r3") = arg4;
107 register u32 r4 asm("r4") = arg5;
108 register u32 r5 asm("r5") = arg6;
109 asm volatile("swi #0"
110 : "=r"(r0)
111 : "r"(r8), "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5)
112 : "memory", "cc");
113 return r0;
114}
115#define __internal_syscall6(n, a1, a2, a3, a4, a5, a6) \
116 (__internal_syscall)(n, (u32)(a1), (long)(a2), (long)(a3), (long)(a4), \
117 (u32)(a5), (long)(a6))
118
119#define __SYSCALL_NARGS_X(a1, a2, a3, a4, a5, a6, a7, a8, n, ...) n
120#define __SYSCALL_NARGS(...) \
121 __SYSCALL_NARGS_X(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0, )
122#define __SYSCALL_CONCAT_X(a, b) a##b
123#define __SYSCALL_CONCAT(a, b) __SYSCALL_CONCAT_X(a, b)
124#define __SYSCALL_DISP(b, ...) \
125 __SYSCALL_CONCAT(b, __SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__)
126
127#define internal_syscall(...) __SYSCALL_DISP(__internal_syscall, __VA_ARGS__)
128
129// Helper function used to avoid cobbler errno.
130bool internal_iserror(uptr retval, int *rverrno) {
131 if (retval >= (uptr)-4095) {
132 if (rverrno)
133 *rverrno = -retval;
134 return true;
135 }
136 return false;
137}
lib/tsan/sanitizer_common/sanitizer_syscall_linux_x86_64.inc created+90
...@@ -0,0 +1,90 @@
1//===-- sanitizer_syscall_linux_x86_64.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// Implementations of internal_syscall and internal_iserror for Linux/x86_64.
10//
11//===----------------------------------------------------------------------===//
12
13#define SYSCALL(name) __NR_ ## name
14
15static uptr internal_syscall(u64 nr) {
16 u64 retval;
17 asm volatile("syscall" : "=a"(retval) : "a"(nr) : "rcx", "r11",
18 "memory", "cc");
19 return retval;
20}
21
22template <typename T1>
23static uptr internal_syscall(u64 nr, T1 arg1) {
24 u64 retval;
25 asm volatile("syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1) :
26 "rcx", "r11", "memory", "cc");
27 return retval;
28}
29
30template <typename T1, typename T2>
31static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2) {
32 u64 retval;
33 asm volatile("syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1),
34 "S"((u64)arg2) : "rcx", "r11", "memory", "cc");
35 return retval;
36}
37
38template <typename T1, typename T2, typename T3>
39static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2, T3 arg3) {
40 u64 retval;
41 asm volatile("syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1),
42 "S"((u64)arg2), "d"((u64)arg3) : "rcx", "r11", "memory", "cc");
43 return retval;
44}
45
46template <typename T1, typename T2, typename T3, typename T4>
47static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2, T3 arg3, T4 arg4) {
48 u64 retval;
49 asm volatile("mov %5, %%r10;"
50 "syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1),
51 "S"((u64)arg2), "d"((u64)arg3), "r"((u64)arg4) :
52 "rcx", "r11", "r10", "memory", "cc");
53 return retval;
54}
55
56template <typename T1, typename T2, typename T3, typename T4, typename T5>
57static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2, T3 arg3, T4 arg4,
58 T5 arg5) {
59 u64 retval;
60 asm volatile("mov %5, %%r10;"
61 "mov %6, %%r8;"
62 "syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1),
63 "S"((u64)arg2), "d"((u64)arg3), "r"((u64)arg4), "r"((u64)arg5) :
64 "rcx", "r11", "r10", "r8", "memory", "cc");
65 return retval;
66}
67
68template <typename T1, typename T2, typename T3, typename T4, typename T5,
69 typename T6>
70static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2, T3 arg3, T4 arg4,
71 T5 arg5, T6 arg6) {
72 u64 retval;
73 asm volatile("mov %5, %%r10;"
74 "mov %6, %%r8;"
75 "mov %7, %%r9;"
76 "syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1),
77 "S"((u64)arg2), "d"((u64)arg3), "r"((u64)arg4), "r"((u64)arg5),
78 "r"((u64)arg6) : "rcx", "r11", "r10", "r8", "r9",
79 "memory", "cc");
80 return retval;
81}
82
83bool internal_iserror(uptr retval, int *rverrno) {
84 if (retval >= (uptr)-4095) {
85 if (rverrno)
86 *rverrno = -retval;
87 return true;
88 }
89 return false;
90}
lib/tsan/sanitizer_common/sanitizer_syscalls_netbsd.inc created+3837
...@@ -0,0 +1,3837 @@
1//===-- sanitizer_syscalls_netbsd.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// Common syscalls handlers for tools like AddressSanitizer,
10// ThreadSanitizer, MemorySanitizer, etc.
11//
12// This file should be included into the tool's interceptor file,
13// which has to define it's own macros:
14// COMMON_SYSCALL_PRE_READ_RANGE
15// Called in prehook for regions that will be read by the kernel and
16// must be initialized.
17// COMMON_SYSCALL_PRE_WRITE_RANGE
18// Called in prehook for regions that will be written to by the kernel
19// and must be addressable. The actual write range may be smaller than
20// reported in the prehook. See POST_WRITE_RANGE.
21// COMMON_SYSCALL_POST_READ_RANGE
22// Called in posthook for regions that were read by the kernel. Does
23// not make much sense.
24// COMMON_SYSCALL_POST_WRITE_RANGE
25// Called in posthook for regions that were written to by the kernel
26// and are now initialized.
27// COMMON_SYSCALL_ACQUIRE(addr)
28// Acquire memory visibility from addr.
29// COMMON_SYSCALL_RELEASE(addr)
30// Release memory visibility to addr.
31// COMMON_SYSCALL_FD_CLOSE(fd)
32// Called before closing file descriptor fd.
33// COMMON_SYSCALL_FD_ACQUIRE(fd)
34// Acquire memory visibility from fd.
35// COMMON_SYSCALL_FD_RELEASE(fd)
36// Release memory visibility to fd.
37// COMMON_SYSCALL_PRE_FORK()
38// Called before fork syscall.
39// COMMON_SYSCALL_POST_FORK(long long res)
40// Called after fork syscall.
41//
42// DO NOT EDIT! THIS FILE HAS BEEN GENERATED!
43//
44// Generated with: generate_netbsd_syscalls.awk
45// Generated date: 2019-12-24
46// Generated from: syscalls.master,v 1.296 2019/09/22 22:59:39 christos Exp
47//
48//===----------------------------------------------------------------------===//
49
50#include "sanitizer_platform.h"
51#if SANITIZER_NETBSD
52
53#include "sanitizer_libc.h"
54
55#define PRE_SYSCALL(name) \
56 SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_syscall_pre_impl_##name
57#define PRE_READ(p, s) COMMON_SYSCALL_PRE_READ_RANGE(p, s)
58#define PRE_WRITE(p, s) COMMON_SYSCALL_PRE_WRITE_RANGE(p, s)
59
60#define POST_SYSCALL(name) \
61 SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_syscall_post_impl_##name
62#define POST_READ(p, s) COMMON_SYSCALL_POST_READ_RANGE(p, s)
63#define POST_WRITE(p, s) COMMON_SYSCALL_POST_WRITE_RANGE(p, s)
64
65#ifndef COMMON_SYSCALL_ACQUIRE
66#define COMMON_SYSCALL_ACQUIRE(addr) ((void)(addr))
67#endif
68
69#ifndef COMMON_SYSCALL_RELEASE
70#define COMMON_SYSCALL_RELEASE(addr) ((void)(addr))
71#endif
72
73#ifndef COMMON_SYSCALL_FD_CLOSE
74#define COMMON_SYSCALL_FD_CLOSE(fd) ((void)(fd))
75#endif
76
77#ifndef COMMON_SYSCALL_FD_ACQUIRE
78#define COMMON_SYSCALL_FD_ACQUIRE(fd) ((void)(fd))
79#endif
80
81#ifndef COMMON_SYSCALL_FD_RELEASE
82#define COMMON_SYSCALL_FD_RELEASE(fd) ((void)(fd))
83#endif
84
85#ifndef COMMON_SYSCALL_PRE_FORK
86#define COMMON_SYSCALL_PRE_FORK() \
87 {}
88#endif
89
90#ifndef COMMON_SYSCALL_POST_FORK
91#define COMMON_SYSCALL_POST_FORK(res) \
92 {}
93#endif
94
95// FIXME: do some kind of PRE_READ for all syscall arguments (int(s) and such).
96
97extern "C" {
98#define SYS_MAXSYSARGS 8
99PRE_SYSCALL(syscall)(long long code_, long long args_[SYS_MAXSYSARGS]) {
100 /* Nothing to do */
101}
102POST_SYSCALL(syscall)
103(long long res, long long code_, long long args_[SYS_MAXSYSARGS]) {
104 /* Nothing to do */
105}
106PRE_SYSCALL(exit)(long long rval_) { /* Nothing to do */ }
107POST_SYSCALL(exit)(long long res, long long rval_) { /* Nothing to do */ }
108PRE_SYSCALL(fork)(void) { COMMON_SYSCALL_PRE_FORK(); }
109POST_SYSCALL(fork)(long long res) { COMMON_SYSCALL_POST_FORK(res); }
110PRE_SYSCALL(read)(long long fd_, void *buf_, long long nbyte_) {
111 if (buf_) {
112 PRE_WRITE(buf_, nbyte_);
113 }
114}
115POST_SYSCALL(read)(long long res, long long fd_, void *buf_, long long nbyte_) {
116 if (res > 0) {
117 POST_WRITE(buf_, res);
118 }
119}
120PRE_SYSCALL(write)(long long fd_, void *buf_, long long nbyte_) {
121 if (buf_) {
122 PRE_READ(buf_, nbyte_);
123 }
124}
125POST_SYSCALL(write)
126(long long res, long long fd_, void *buf_, long long nbyte_) {
127 if (res > 0) {
128 POST_READ(buf_, res);
129 }
130}
131PRE_SYSCALL(open)(void *path_, long long flags_, long long mode_) {
132 const char *path = (const char *)path_;
133 if (path) {
134 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
135 }
136}
137POST_SYSCALL(open)
138(long long res, void *path_, long long flags_, long long mode_) {
139 if (res > 0) {
140 const char *path = (const char *)path_;
141 if (path) {
142 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
143 }
144 }
145}
146PRE_SYSCALL(close)(long long fd_) { COMMON_SYSCALL_FD_CLOSE((int)fd_); }
147POST_SYSCALL(close)(long long res, long long fd_) { /* Nothing to do */ }
148PRE_SYSCALL(compat_50_wait4)
149(long long pid_, void *status_, long long options_, void *rusage_) {
150 /* TODO */
151}
152POST_SYSCALL(compat_50_wait4)
153(long long res, long long pid_, void *status_, long long options_,
154 void *rusage_) {
155 /* TODO */
156}
157PRE_SYSCALL(compat_43_ocreat)(void *path_, long long mode_) { /* TODO */ }
158POST_SYSCALL(compat_43_ocreat)(long long res, void *path_, long long mode_) {
159 /* TODO */
160}
161PRE_SYSCALL(link)(void *path_, void *link_) {
162 const char *path = (const char *)path_;
163 const char *link = (const char *)link_;
164 if (path) {
165 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
166 }
167 if (link) {
168 PRE_READ(path, __sanitizer::internal_strlen(link) + 1);
169 }
170}
171POST_SYSCALL(link)(long long res, void *path_, void *link_) {
172 if (res == 0) {
173 const char *path = (const char *)path_;
174 const char *link = (const char *)link_;
175 if (path) {
176 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
177 }
178 if (link) {
179 POST_READ(path, __sanitizer::internal_strlen(link) + 1);
180 }
181 }
182}
183PRE_SYSCALL(unlink)(void *path_) {
184 const char *path = (const char *)path_;
185 if (path) {
186 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
187 }
188}
189POST_SYSCALL(unlink)(long long res, void *path_) {
190 if (res == 0) {
191 const char *path = (const char *)path_;
192 if (path) {
193 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
194 }
195 }
196}
197/* syscall 11 has been skipped */
198PRE_SYSCALL(chdir)(void *path_) {
199 const char *path = (const char *)path_;
200 if (path) {
201 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
202 }
203}
204POST_SYSCALL(chdir)(long long res, void *path_) {
205 if (res == 0) {
206 const char *path = (const char *)path_;
207 if (path) {
208 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
209 }
210 }
211}
212PRE_SYSCALL(fchdir)(long long fd_) { /* Nothing to do */ }
213POST_SYSCALL(fchdir)(long long res, long long fd_) { /* Nothing to do */ }
214PRE_SYSCALL(compat_50_mknod)(void *path_, long long mode_, long long dev_) {
215 /* TODO */
216}
217POST_SYSCALL(compat_50_mknod)
218(long long res, void *path_, long long mode_, long long dev_) {
219 /* TODO */
220}
221PRE_SYSCALL(chmod)(void *path_, long long mode_) {
222 const char *path = (const char *)path_;
223 if (path) {
224 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
225 }
226}
227POST_SYSCALL(chmod)(long long res, void *path_, long long mode_) {
228 if (res == 0) {
229 const char *path = (const char *)path_;
230 if (path) {
231 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
232 }
233 }
234}
235PRE_SYSCALL(chown)(void *path_, long long uid_, long long gid_) {
236 const char *path = (const char *)path_;
237 if (path) {
238 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
239 }
240}
241POST_SYSCALL(chown)
242(long long res, void *path_, long long uid_, long long gid_) {
243 if (res == 0) {
244 const char *path = (const char *)path_;
245 if (path) {
246 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
247 }
248 }
249}
250PRE_SYSCALL(break)(void *nsize_) { /* Nothing to do */ }
251POST_SYSCALL(break)(long long res, void *nsize_) { /* Nothing to do */ }
252PRE_SYSCALL(compat_20_getfsstat)
253(void *buf_, long long bufsize_, long long flags_) {
254 /* TODO */
255}
256POST_SYSCALL(compat_20_getfsstat)
257(long long res, void *buf_, long long bufsize_, long long flags_) {
258 /* TODO */
259}
260PRE_SYSCALL(compat_43_olseek)
261(long long fd_, long long offset_, long long whence_) {
262 /* TODO */
263}
264POST_SYSCALL(compat_43_olseek)
265(long long res, long long fd_, long long offset_, long long whence_) {
266 /* TODO */
267}
268PRE_SYSCALL(getpid)(void) { /* Nothing to do */ }
269POST_SYSCALL(getpid)(long long res) { /* Nothing to do */ }
270PRE_SYSCALL(compat_40_mount)
271(void *type_, void *path_, long long flags_, void *data_) {
272 /* TODO */
273}
274POST_SYSCALL(compat_40_mount)
275(long long res, void *type_, void *path_, long long flags_, void *data_) {
276 /* TODO */
277}
278PRE_SYSCALL(unmount)(void *path_, long long flags_) {
279 const char *path = (const char *)path_;
280 if (path) {
281 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
282 }
283}
284POST_SYSCALL(unmount)(long long res, void *path_, long long flags_) {
285 if (res == 0) {
286 const char *path = (const char *)path_;
287 if (path) {
288 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
289 }
290 }
291}
292PRE_SYSCALL(setuid)(long long uid_) { /* Nothing to do */ }
293POST_SYSCALL(setuid)(long long res, long long uid_) { /* Nothing to do */ }
294PRE_SYSCALL(getuid)(void) { /* Nothing to do */ }
295POST_SYSCALL(getuid)(long long res) { /* Nothing to do */ }
296PRE_SYSCALL(geteuid)(void) { /* Nothing to do */ }
297POST_SYSCALL(geteuid)(long long res) { /* Nothing to do */ }
298PRE_SYSCALL(ptrace)
299(long long req_, long long pid_, void *addr_, long long data_) {
300 if (req_ == ptrace_pt_io) {
301 struct __sanitizer_ptrace_io_desc *addr =
302 (struct __sanitizer_ptrace_io_desc *)addr_;
303 PRE_READ(addr, struct_ptrace_ptrace_io_desc_struct_sz);
304 if (addr->piod_op == ptrace_piod_write_d ||
305 addr->piod_op == ptrace_piod_write_i) {
306 PRE_READ(addr->piod_addr, addr->piod_len);
307 }
308 if (addr->piod_op == ptrace_piod_read_d ||
309 addr->piod_op == ptrace_piod_read_i ||
310 addr->piod_op == ptrace_piod_read_auxv) {
311 PRE_WRITE(addr->piod_addr, addr->piod_len);
312 }
313 } else if (req_ == ptrace_pt_lwpinfo) {
314 struct __sanitizer_ptrace_lwpinfo *addr =
315 (struct __sanitizer_ptrace_lwpinfo *)addr_;
316 PRE_READ(&addr->pl_lwpid, sizeof(__sanitizer_lwpid_t));
317 PRE_WRITE(addr, struct_ptrace_ptrace_lwpinfo_struct_sz);
318 } else if (req_ == ptrace_pt_set_event_mask) {
319 PRE_READ(addr_, struct_ptrace_ptrace_event_struct_sz);
320 } else if (req_ == ptrace_pt_get_event_mask) {
321 PRE_WRITE(addr_, struct_ptrace_ptrace_event_struct_sz);
322 } else if (req_ == ptrace_pt_set_siginfo) {
323 PRE_READ(addr_, struct_ptrace_ptrace_siginfo_struct_sz);
324 } else if (req_ == ptrace_pt_get_siginfo) {
325 PRE_WRITE(addr_, struct_ptrace_ptrace_siginfo_struct_sz);
326 } else if (req_ == ptrace_pt_lwpstatus) {
327 struct __sanitizer_ptrace_lwpstatus *addr =
328 (struct __sanitizer_ptrace_lwpstatus *)addr_;
329 PRE_READ(&addr->pl_lwpid, sizeof(__sanitizer_lwpid_t));
330 PRE_WRITE(addr, struct_ptrace_ptrace_lwpstatus_struct_sz);
331 } else if (req_ == ptrace_pt_lwpnext) {
332 struct __sanitizer_ptrace_lwpstatus *addr =
333 (struct __sanitizer_ptrace_lwpstatus *)addr_;
334 PRE_READ(&addr->pl_lwpid, sizeof(__sanitizer_lwpid_t));
335 PRE_WRITE(addr, struct_ptrace_ptrace_lwpstatus_struct_sz);
336 } else if (req_ == ptrace_pt_setregs) {
337 PRE_READ(addr_, struct_ptrace_reg_struct_sz);
338 } else if (req_ == ptrace_pt_getregs) {
339 PRE_WRITE(addr_, struct_ptrace_reg_struct_sz);
340 } else if (req_ == ptrace_pt_setfpregs) {
341 PRE_READ(addr_, struct_ptrace_fpreg_struct_sz);
342 } else if (req_ == ptrace_pt_getfpregs) {
343 PRE_WRITE(addr_, struct_ptrace_fpreg_struct_sz);
344 } else if (req_ == ptrace_pt_setdbregs) {
345 PRE_READ(addr_, struct_ptrace_dbreg_struct_sz);
346 } else if (req_ == ptrace_pt_getdbregs) {
347 PRE_WRITE(addr_, struct_ptrace_dbreg_struct_sz);
348 }
349}
350POST_SYSCALL(ptrace)
351(long long res, long long req_, long long pid_, void *addr_, long long data_) {
352 if (res == 0) {
353 if (req_ == ptrace_pt_io) {
354 struct __sanitizer_ptrace_io_desc *addr =
355 (struct __sanitizer_ptrace_io_desc *)addr_;
356 POST_READ(addr, struct_ptrace_ptrace_io_desc_struct_sz);
357 if (addr->piod_op == ptrace_piod_write_d ||
358 addr->piod_op == ptrace_piod_write_i) {
359 POST_READ(addr->piod_addr, addr->piod_len);
360 }
361 if (addr->piod_op == ptrace_piod_read_d ||
362 addr->piod_op == ptrace_piod_read_i ||
363 addr->piod_op == ptrace_piod_read_auxv) {
364 POST_WRITE(addr->piod_addr, addr->piod_len);
365 }
366 } else if (req_ == ptrace_pt_lwpinfo) {
367 struct __sanitizer_ptrace_lwpinfo *addr =
368 (struct __sanitizer_ptrace_lwpinfo *)addr_;
369 POST_READ(&addr->pl_lwpid, sizeof(__sanitizer_lwpid_t));
370 POST_WRITE(addr, struct_ptrace_ptrace_lwpinfo_struct_sz);
371 } else if (req_ == ptrace_pt_set_event_mask) {
372 POST_READ(addr_, struct_ptrace_ptrace_event_struct_sz);
373 } else if (req_ == ptrace_pt_get_event_mask) {
374 POST_WRITE(addr_, struct_ptrace_ptrace_event_struct_sz);
375 } else if (req_ == ptrace_pt_set_siginfo) {
376 POST_READ(addr_, struct_ptrace_ptrace_siginfo_struct_sz);
377 } else if (req_ == ptrace_pt_get_siginfo) {
378 POST_WRITE(addr_, struct_ptrace_ptrace_siginfo_struct_sz);
379 } else if (req_ == ptrace_pt_lwpstatus) {
380 struct __sanitizer_ptrace_lwpstatus *addr =
381 (struct __sanitizer_ptrace_lwpstatus *)addr_;
382 POST_READ(&addr->pl_lwpid, sizeof(__sanitizer_lwpid_t));
383 POST_WRITE(addr, struct_ptrace_ptrace_lwpstatus_struct_sz);
384 } else if (req_ == ptrace_pt_lwpnext) {
385 struct __sanitizer_ptrace_lwpstatus *addr =
386 (struct __sanitizer_ptrace_lwpstatus *)addr_;
387 POST_READ(&addr->pl_lwpid, sizeof(__sanitizer_lwpid_t));
388 POST_WRITE(addr, struct_ptrace_ptrace_lwpstatus_struct_sz);
389 } else if (req_ == ptrace_pt_setregs) {
390 POST_READ(addr_, struct_ptrace_reg_struct_sz);
391 } else if (req_ == ptrace_pt_getregs) {
392 POST_WRITE(addr_, struct_ptrace_reg_struct_sz);
393 } else if (req_ == ptrace_pt_setfpregs) {
394 POST_READ(addr_, struct_ptrace_fpreg_struct_sz);
395 } else if (req_ == ptrace_pt_getfpregs) {
396 POST_WRITE(addr_, struct_ptrace_fpreg_struct_sz);
397 } else if (req_ == ptrace_pt_setdbregs) {
398 POST_READ(addr_, struct_ptrace_dbreg_struct_sz);
399 } else if (req_ == ptrace_pt_getdbregs) {
400 POST_WRITE(addr_, struct_ptrace_dbreg_struct_sz);
401 }
402 }
403}
404PRE_SYSCALL(recvmsg)(long long s_, void *msg_, long long flags_) {
405 PRE_WRITE(msg_, sizeof(__sanitizer_msghdr));
406}
407POST_SYSCALL(recvmsg)
408(long long res, long long s_, void *msg_, long long flags_) {
409 if (res > 0) {
410 POST_WRITE(msg_, sizeof(__sanitizer_msghdr));
411 }
412}
413PRE_SYSCALL(sendmsg)(long long s_, void *msg_, long long flags_) {
414 PRE_READ(msg_, sizeof(__sanitizer_msghdr));
415}
416POST_SYSCALL(sendmsg)
417(long long res, long long s_, void *msg_, long long flags_) {
418 if (res > 0) {
419 POST_READ(msg_, sizeof(__sanitizer_msghdr));
420 }
421}
422PRE_SYSCALL(recvfrom)
423(long long s_, void *buf_, long long len_, long long flags_, void *from_,
424 void *fromlenaddr_) {
425 PRE_WRITE(buf_, len_);
426 PRE_WRITE(from_, struct_sockaddr_sz);
427 PRE_WRITE(fromlenaddr_, sizeof(__sanitizer_socklen_t));
428}
429POST_SYSCALL(recvfrom)
430(long long res, long long s_, void *buf_, long long len_, long long flags_,
431 void *from_, void *fromlenaddr_) {
432 if (res >= 0) {
433 POST_WRITE(buf_, res);
434 POST_WRITE(from_, struct_sockaddr_sz);
435 POST_WRITE(fromlenaddr_, sizeof(__sanitizer_socklen_t));
436 }
437}
438PRE_SYSCALL(accept)(long long s_, void *name_, void *anamelen_) {
439 PRE_WRITE(name_, struct_sockaddr_sz);
440 PRE_WRITE(anamelen_, sizeof(__sanitizer_socklen_t));
441}
442POST_SYSCALL(accept)
443(long long res, long long s_, void *name_, void *anamelen_) {
444 if (res == 0) {
445 POST_WRITE(name_, struct_sockaddr_sz);
446 POST_WRITE(anamelen_, sizeof(__sanitizer_socklen_t));
447 }
448}
449PRE_SYSCALL(getpeername)(long long fdes_, void *asa_, void *alen_) {
450 PRE_WRITE(asa_, struct_sockaddr_sz);
451 PRE_WRITE(alen_, sizeof(__sanitizer_socklen_t));
452}
453POST_SYSCALL(getpeername)
454(long long res, long long fdes_, void *asa_, void *alen_) {
455 if (res == 0) {
456 POST_WRITE(asa_, struct_sockaddr_sz);
457 POST_WRITE(alen_, sizeof(__sanitizer_socklen_t));
458 }
459}
460PRE_SYSCALL(getsockname)(long long fdes_, void *asa_, void *alen_) {
461 PRE_WRITE(asa_, struct_sockaddr_sz);
462 PRE_WRITE(alen_, sizeof(__sanitizer_socklen_t));
463}
464POST_SYSCALL(getsockname)
465(long long res, long long fdes_, void *asa_, void *alen_) {
466 if (res == 0) {
467 POST_WRITE(asa_, struct_sockaddr_sz);
468 POST_WRITE(alen_, sizeof(__sanitizer_socklen_t));
469 }
470}
471PRE_SYSCALL(access)(void *path_, long long flags_) {
472 const char *path = (const char *)path_;
473 if (path) {
474 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
475 }
476}
477POST_SYSCALL(access)(long long res, void *path_, long long flags_) {
478 if (res == 0) {
479 const char *path = (const char *)path_;
480 if (path) {
481 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
482 }
483 }
484}
485PRE_SYSCALL(chflags)(void *path_, long long flags_) {
486 const char *path = (const char *)path_;
487 if (path) {
488 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
489 }
490}
491POST_SYSCALL(chflags)(long long res, void *path_, long long flags_) {
492 if (res == 0) {
493 const char *path = (const char *)path_;
494 if (path) {
495 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
496 }
497 }
498}
499PRE_SYSCALL(fchflags)(long long fd_, long long flags_) { /* Nothing to do */ }
500POST_SYSCALL(fchflags)(long long res, long long fd_, long long flags_) {
501 /* Nothing to do */
502}
503PRE_SYSCALL(sync)(void) { /* Nothing to do */ }
504POST_SYSCALL(sync)(long long res) { /* Nothing to do */ }
505PRE_SYSCALL(kill)(long long pid_, long long signum_) { /* Nothing to do */ }
506POST_SYSCALL(kill)(long long res, long long pid_, long long signum_) {
507 /* Nothing to do */
508}
509PRE_SYSCALL(compat_43_stat43)(void *path_, void *ub_) { /* TODO */ }
510POST_SYSCALL(compat_43_stat43)(long long res, void *path_, void *ub_) {
511 /* TODO */
512}
513PRE_SYSCALL(getppid)(void) { /* Nothing to do */ }
514POST_SYSCALL(getppid)(long long res) { /* Nothing to do */ }
515PRE_SYSCALL(compat_43_lstat43)(void *path_, void *ub_) { /* TODO */ }
516POST_SYSCALL(compat_43_lstat43)(long long res, void *path_, void *ub_) {
517 /* TODO */
518}
519PRE_SYSCALL(dup)(long long fd_) { /* Nothing to do */ }
520POST_SYSCALL(dup)(long long res, long long fd_) { /* Nothing to do */ }
521PRE_SYSCALL(pipe)(void) {
522 /* pipe returns two descriptors through two returned values */
523}
524POST_SYSCALL(pipe)(long long res) {
525 /* pipe returns two descriptors through two returned values */
526}
527PRE_SYSCALL(getegid)(void) { /* Nothing to do */ }
528POST_SYSCALL(getegid)(long long res) { /* Nothing to do */ }
529PRE_SYSCALL(profil)
530(void *samples_, long long size_, long long offset_, long long scale_) {
531 if (samples_) {
532 PRE_WRITE(samples_, size_);
533 }
534}
535POST_SYSCALL(profil)
536(long long res, void *samples_, long long size_, long long offset_,
537 long long scale_) {
538 if (res == 0) {
539 if (samples_) {
540 POST_WRITE(samples_, size_);
541 }
542 }
543}
544PRE_SYSCALL(ktrace)
545(void *fname_, long long ops_, long long facs_, long long pid_) {
546 const char *fname = (const char *)fname_;
547 if (fname) {
548 PRE_READ(fname, __sanitizer::internal_strlen(fname) + 1);
549 }
550}
551POST_SYSCALL(ktrace)
552(long long res, void *fname_, long long ops_, long long facs_, long long pid_) {
553 const char *fname = (const char *)fname_;
554 if (res == 0) {
555 if (fname) {
556 POST_READ(fname, __sanitizer::internal_strlen(fname) + 1);
557 }
558 }
559}
560PRE_SYSCALL(compat_13_sigaction13)(long long signum_, void *nsa_, void *osa_) {
561 /* TODO */
562}
563POST_SYSCALL(compat_13_sigaction13)
564(long long res, long long signum_, void *nsa_, void *osa_) {
565 /* TODO */
566}
567PRE_SYSCALL(getgid)(void) { /* Nothing to do */ }
568POST_SYSCALL(getgid)(long long res) { /* Nothing to do */ }
569PRE_SYSCALL(compat_13_sigprocmask13)(long long how_, long long mask_) {
570 /* TODO */
571}
572POST_SYSCALL(compat_13_sigprocmask13)
573(long long res, long long how_, long long mask_) {
574 /* TODO */
575}
576PRE_SYSCALL(__getlogin)(void *namebuf_, long long namelen_) {
577 if (namebuf_) {
578 PRE_WRITE(namebuf_, namelen_);
579 }
580}
581POST_SYSCALL(__getlogin)(long long res, void *namebuf_, long long namelen_) {
582 if (res == 0) {
583 if (namebuf_) {
584 POST_WRITE(namebuf_, namelen_);
585 }
586 }
587}
588PRE_SYSCALL(__setlogin)(void *namebuf_) {
589 const char *namebuf = (const char *)namebuf_;
590 if (namebuf) {
591 PRE_READ(namebuf, __sanitizer::internal_strlen(namebuf) + 1);
592 }
593}
594POST_SYSCALL(__setlogin)(long long res, void *namebuf_) {
595 if (res == 0) {
596 const char *namebuf = (const char *)namebuf_;
597 if (namebuf) {
598 POST_READ(namebuf, __sanitizer::internal_strlen(namebuf) + 1);
599 }
600 }
601}
602PRE_SYSCALL(acct)(void *path_) {
603 const char *path = (const char *)path_;
604 if (path) {
605 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
606 }
607}
608POST_SYSCALL(acct)(long long res, void *path_) {
609 if (res == 0) {
610 const char *path = (const char *)path_;
611 if (path) {
612 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
613 }
614 }
615}
616PRE_SYSCALL(compat_13_sigpending13)(void) { /* TODO */ }
617POST_SYSCALL(compat_13_sigpending13)(long long res) { /* TODO */ }
618PRE_SYSCALL(compat_13_sigaltstack13)(void *nss_, void *oss_) { /* TODO */ }
619POST_SYSCALL(compat_13_sigaltstack13)(long long res, void *nss_, void *oss_) {
620 /* TODO */
621}
622PRE_SYSCALL(ioctl)(long long fd_, long long com_, void *data_) {
623 /* Nothing to do */
624}
625POST_SYSCALL(ioctl)(long long res, long long fd_, long long com_, void *data_) {
626 /* Nothing to do */
627}
628PRE_SYSCALL(compat_12_oreboot)(long long opt_) { /* TODO */ }
629POST_SYSCALL(compat_12_oreboot)(long long res, long long opt_) { /* TODO */ }
630PRE_SYSCALL(revoke)(void *path_) {
631 const char *path = (const char *)path_;
632 if (path) {
633 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
634 }
635}
636POST_SYSCALL(revoke)(long long res, void *path_) {
637 if (res == 0) {
638 const char *path = (const char *)path_;
639 if (path) {
640 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
641 }
642 }
643}
644PRE_SYSCALL(symlink)(void *path_, void *link_) {
645 const char *path = (const char *)path_;
646 const char *link = (const char *)link_;
647 if (path) {
648 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
649 }
650 if (link) {
651 PRE_READ(link, __sanitizer::internal_strlen(link) + 1);
652 }
653}
654POST_SYSCALL(symlink)(long long res, void *path_, void *link_) {
655 if (res == 0) {
656 const char *path = (const char *)path_;
657 const char *link = (const char *)link_;
658 if (path) {
659 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
660 }
661 if (link) {
662 POST_READ(link, __sanitizer::internal_strlen(link) + 1);
663 }
664 }
665}
666PRE_SYSCALL(readlink)(void *path_, void *buf_, long long count_) {
667 const char *path = (const char *)path_;
668 if (path) {
669 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
670 }
671 if (buf_) {
672 PRE_WRITE(buf_, count_);
673 }
674}
675POST_SYSCALL(readlink)
676(long long res, void *path_, void *buf_, long long count_) {
677 if (res > 0) {
678 const char *path = (const char *)path_;
679 if (path) {
680 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
681 }
682 if (buf_) {
683 PRE_WRITE(buf_, res);
684 }
685 }
686}
687PRE_SYSCALL(execve)(void *path_, void *argp_, void *envp_) {
688 const char *path = (const char *)path_;
689 char **argp = (char **)argp_;
690 char **envp = (char **)envp_;
691 if (path) {
692 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
693 }
694 if (argp && argp[0]) {
695 char *a = argp[0];
696 while (a++) {
697 PRE_READ(a, __sanitizer::internal_strlen(a) + 1);
698 }
699 }
700 if (envp && envp[0]) {
701 char *e = envp[0];
702 while (e++) {
703 PRE_READ(e, __sanitizer::internal_strlen(e) + 1);
704 }
705 }
706}
707POST_SYSCALL(execve)(long long res, void *path_, void *argp_, void *envp_) {
708 /* If we are here, something went wrong */
709 const char *path = (const char *)path_;
710 char **argp = (char **)argp_;
711 char **envp = (char **)envp_;
712 if (path) {
713 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
714 }
715 if (argp && argp[0]) {
716 char *a = argp[0];
717 while (a++) {
718 POST_READ(a, __sanitizer::internal_strlen(a) + 1);
719 }
720 }
721 if (envp && envp[0]) {
722 char *e = envp[0];
723 while (e++) {
724 POST_READ(e, __sanitizer::internal_strlen(e) + 1);
725 }
726 }
727}
728PRE_SYSCALL(umask)(long long newmask_) { /* Nothing to do */ }
729POST_SYSCALL(umask)(long long res, long long newmask_) { /* Nothing to do */ }
730PRE_SYSCALL(chroot)(void *path_) {
731 const char *path = (const char *)path_;
732 if (path) {
733 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
734 }
735}
736POST_SYSCALL(chroot)(long long res, void *path_) {
737 if (res == 0) {
738 const char *path = (const char *)path_;
739 if (path) {
740 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
741 }
742 }
743}
744PRE_SYSCALL(compat_43_fstat43)(long long fd_, void *sb_) { /* TODO */ }
745POST_SYSCALL(compat_43_fstat43)(long long res, long long fd_, void *sb_) {
746 /* TODO */
747}
748PRE_SYSCALL(compat_43_ogetkerninfo)
749(long long op_, void *where_, void *size_, long long arg_) {
750 /* TODO */
751}
752POST_SYSCALL(compat_43_ogetkerninfo)
753(long long res, long long op_, void *where_, void *size_, long long arg_) {
754 /* TODO */
755}
756PRE_SYSCALL(compat_43_ogetpagesize)(void) { /* TODO */ }
757POST_SYSCALL(compat_43_ogetpagesize)(long long res) { /* TODO */ }
758PRE_SYSCALL(compat_12_msync)(void *addr_, long long len_) { /* TODO */ }
759POST_SYSCALL(compat_12_msync)(long long res, void *addr_, long long len_) {
760 /* TODO */
761}
762PRE_SYSCALL(vfork)(void) { /* Nothing to do */ }
763POST_SYSCALL(vfork)(long long res) { /* Nothing to do */ }
764/* syscall 67 has been skipped */
765/* syscall 68 has been skipped */
766/* syscall 69 has been skipped */
767/* syscall 70 has been skipped */
768PRE_SYSCALL(compat_43_ommap)
769(void *addr_, long long len_, long long prot_, long long flags_, long long fd_,
770 long long pos_) {
771 /* TODO */
772}
773POST_SYSCALL(compat_43_ommap)
774(long long res, void *addr_, long long len_, long long prot_, long long flags_,
775 long long fd_, long long pos_) {
776 /* TODO */
777}
778PRE_SYSCALL(vadvise)(long long anom_) { /* Nothing to do */ }
779POST_SYSCALL(vadvise)(long long res, long long anom_) { /* Nothing to do */ }
780PRE_SYSCALL(munmap)(void *addr_, long long len_) { /* Nothing to do */ }
781POST_SYSCALL(munmap)(long long res, void *addr_, long long len_) {
782 /* Nothing to do */
783}
784PRE_SYSCALL(mprotect)(void *addr_, long long len_, long long prot_) {
785 /* Nothing to do */
786}
787POST_SYSCALL(mprotect)
788(long long res, void *addr_, long long len_, long long prot_) {
789 /* Nothing to do */
790}
791PRE_SYSCALL(madvise)(void *addr_, long long len_, long long behav_) {
792 /* Nothing to do */
793}
794POST_SYSCALL(madvise)
795(long long res, void *addr_, long long len_, long long behav_) {
796 /* Nothing to do */
797}
798/* syscall 76 has been skipped */
799/* syscall 77 has been skipped */
800PRE_SYSCALL(mincore)(void *addr_, long long len_, void *vec_) {
801 /* Nothing to do */
802}
803POST_SYSCALL(mincore)(long long res, void *addr_, long long len_, void *vec_) {
804 /* Nothing to do */
805}
806PRE_SYSCALL(getgroups)(long long gidsetsize_, void *gidset_) {
807 unsigned int *gidset = (unsigned int *)gidset_;
808 if (gidset) {
809 PRE_WRITE(gidset, sizeof(*gidset) * gidsetsize_);
810 }
811}
812POST_SYSCALL(getgroups)(long long res, long long gidsetsize_, void *gidset_) {
813 if (res == 0) {
814 unsigned int *gidset = (unsigned int *)gidset_;
815 if (gidset) {
816 POST_WRITE(gidset, sizeof(*gidset) * gidsetsize_);
817 }
818 }
819}
820PRE_SYSCALL(setgroups)(long long gidsetsize_, void *gidset_) {
821 unsigned int *gidset = (unsigned int *)gidset_;
822 if (gidset) {
823 PRE_READ(gidset, sizeof(*gidset) * gidsetsize_);
824 }
825}
826POST_SYSCALL(setgroups)(long long res, long long gidsetsize_, void *gidset_) {
827 if (res == 0) {
828 unsigned int *gidset = (unsigned int *)gidset_;
829 if (gidset) {
830 POST_READ(gidset, sizeof(*gidset) * gidsetsize_);
831 }
832 }
833}
834PRE_SYSCALL(getpgrp)(void) { /* Nothing to do */ }
835POST_SYSCALL(getpgrp)(long long res) { /* Nothing to do */ }
836PRE_SYSCALL(setpgid)(long long pid_, long long pgid_) { /* Nothing to do */ }
837POST_SYSCALL(setpgid)(long long res, long long pid_, long long pgid_) {
838 /* Nothing to do */
839}
840PRE_SYSCALL(compat_50_setitimer)(long long which_, void *itv_, void *oitv_) {
841 /* TODO */
842}
843POST_SYSCALL(compat_50_setitimer)
844(long long res, long long which_, void *itv_, void *oitv_) {
845 /* TODO */
846}
847PRE_SYSCALL(compat_43_owait)(void) { /* TODO */ }
848POST_SYSCALL(compat_43_owait)(long long res) { /* TODO */ }
849PRE_SYSCALL(compat_12_oswapon)(void *name_) { /* TODO */ }
850POST_SYSCALL(compat_12_oswapon)(long long res, void *name_) { /* TODO */ }
851PRE_SYSCALL(compat_50_getitimer)(long long which_, void *itv_) { /* TODO */ }
852POST_SYSCALL(compat_50_getitimer)(long long res, long long which_, void *itv_) {
853 /* TODO */
854}
855PRE_SYSCALL(compat_43_ogethostname)(void *hostname_, long long len_) {
856 /* TODO */
857}
858POST_SYSCALL(compat_43_ogethostname)
859(long long res, void *hostname_, long long len_) {
860 /* TODO */
861}
862PRE_SYSCALL(compat_43_osethostname)(void *hostname_, long long len_) {
863 /* TODO */
864}
865POST_SYSCALL(compat_43_osethostname)
866(long long res, void *hostname_, long long len_) {
867 /* TODO */
868}
869PRE_SYSCALL(compat_43_ogetdtablesize)(void) { /* TODO */ }
870POST_SYSCALL(compat_43_ogetdtablesize)(long long res) { /* TODO */ }
871PRE_SYSCALL(dup2)(long long from_, long long to_) { /* Nothing to do */ }
872POST_SYSCALL(dup2)(long long res, long long from_, long long to_) {
873 /* Nothing to do */
874}
875/* syscall 91 has been skipped */
876PRE_SYSCALL(fcntl)(long long fd_, long long cmd_, void *arg_) {
877 /* Nothing to do */
878}
879POST_SYSCALL(fcntl)(long long res, long long fd_, long long cmd_, void *arg_) {
880 /* Nothing to do */
881}
882PRE_SYSCALL(compat_50_select)
883(long long nd_, void *in_, void *ou_, void *ex_, void *tv_) {
884 /* TODO */
885}
886POST_SYSCALL(compat_50_select)
887(long long res, long long nd_, void *in_, void *ou_, void *ex_, void *tv_) {
888 /* TODO */
889}
890/* syscall 94 has been skipped */
891PRE_SYSCALL(fsync)(long long fd_) { /* Nothing to do */ }
892POST_SYSCALL(fsync)(long long res, long long fd_) { /* Nothing to do */ }
893PRE_SYSCALL(setpriority)(long long which_, long long who_, long long prio_) {
894 /* Nothing to do */
895}
896POST_SYSCALL(setpriority)
897(long long res, long long which_, long long who_, long long prio_) {
898 /* Nothing to do */
899}
900PRE_SYSCALL(compat_30_socket)
901(long long domain_, long long type_, long long protocol_) {
902 /* TODO */
903}
904POST_SYSCALL(compat_30_socket)
905(long long res, long long domain_, long long type_, long long protocol_) {
906 /* TODO */
907}
908PRE_SYSCALL(connect)(long long s_, void *name_, long long namelen_) {
909 PRE_READ(name_, namelen_);
910}
911POST_SYSCALL(connect)
912(long long res, long long s_, void *name_, long long namelen_) {
913 if (res == 0) {
914 POST_READ(name_, namelen_);
915 }
916}
917PRE_SYSCALL(compat_43_oaccept)(long long s_, void *name_, void *anamelen_) {
918 /* TODO */
919}
920POST_SYSCALL(compat_43_oaccept)
921(long long res, long long s_, void *name_, void *anamelen_) {
922 /* TODO */
923}
924PRE_SYSCALL(getpriority)(long long which_, long long who_) {
925 /* Nothing to do */
926}
927POST_SYSCALL(getpriority)(long long res, long long which_, long long who_) {
928 /* Nothing to do */
929}
930PRE_SYSCALL(compat_43_osend)
931(long long s_, void *buf_, long long len_, long long flags_) {
932 /* TODO */
933}
934POST_SYSCALL(compat_43_osend)
935(long long res, long long s_, void *buf_, long long len_, long long flags_) {
936 /* TODO */
937}
938PRE_SYSCALL(compat_43_orecv)
939(long long s_, void *buf_, long long len_, long long flags_) {
940 /* TODO */
941}
942POST_SYSCALL(compat_43_orecv)
943(long long res, long long s_, void *buf_, long long len_, long long flags_) {
944 /* TODO */
945}
946PRE_SYSCALL(compat_13_sigreturn13)(void *sigcntxp_) { /* TODO */ }
947POST_SYSCALL(compat_13_sigreturn13)(long long res, void *sigcntxp_) {
948 /* TODO */
949}
950PRE_SYSCALL(bind)(long long s_, void *name_, long long namelen_) {
951 PRE_READ(name_, namelen_);
952}
953POST_SYSCALL(bind)
954(long long res, long long s_, void *name_, long long namelen_) {
955 if (res == 0) {
956 PRE_READ(name_, namelen_);
957 }
958}
959PRE_SYSCALL(setsockopt)
960(long long s_, long long level_, long long name_, void *val_,
961 long long valsize_) {
962 if (val_) {
963 PRE_READ(val_, valsize_);
964 }
965}
966POST_SYSCALL(setsockopt)
967(long long res, long long s_, long long level_, long long name_, void *val_,
968 long long valsize_) {
969 if (res == 0) {
970 if (val_) {
971 POST_READ(val_, valsize_);
972 }
973 }
974}
975PRE_SYSCALL(listen)(long long s_, long long backlog_) { /* Nothing to do */ }
976POST_SYSCALL(listen)(long long res, long long s_, long long backlog_) {
977 /* Nothing to do */
978}
979/* syscall 107 has been skipped */
980PRE_SYSCALL(compat_43_osigvec)(long long signum_, void *nsv_, void *osv_) {
981 /* TODO */
982}
983POST_SYSCALL(compat_43_osigvec)
984(long long res, long long signum_, void *nsv_, void *osv_) {
985 /* TODO */
986}
987PRE_SYSCALL(compat_43_osigblock)(long long mask_) { /* TODO */ }
988POST_SYSCALL(compat_43_osigblock)(long long res, long long mask_) { /* TODO */ }
989PRE_SYSCALL(compat_43_osigsetmask)(long long mask_) { /* TODO */ }
990POST_SYSCALL(compat_43_osigsetmask)(long long res, long long mask_) {
991 /* TODO */
992}
993PRE_SYSCALL(compat_13_sigsuspend13)(long long mask_) { /* TODO */ }
994POST_SYSCALL(compat_13_sigsuspend13)(long long res, long long mask_) {
995 /* TODO */
996}
997PRE_SYSCALL(compat_43_osigstack)(void *nss_, void *oss_) { /* TODO */ }
998POST_SYSCALL(compat_43_osigstack)(long long res, void *nss_, void *oss_) {
999 /* TODO */
1000}
1001PRE_SYSCALL(compat_43_orecvmsg)(long long s_, void *msg_, long long flags_) {
1002 /* TODO */
1003}
1004POST_SYSCALL(compat_43_orecvmsg)
1005(long long res, long long s_, void *msg_, long long flags_) {
1006 /* TODO */
1007}
1008PRE_SYSCALL(compat_43_osendmsg)(long long s_, void *msg_, long long flags_) {
1009 /* TODO */
1010}
1011POST_SYSCALL(compat_43_osendmsg)
1012(long long res, long long s_, void *msg_, long long flags_) {
1013 /* TODO */
1014}
1015/* syscall 115 has been skipped */
1016PRE_SYSCALL(compat_50_gettimeofday)(void *tp_, void *tzp_) { /* TODO */ }
1017POST_SYSCALL(compat_50_gettimeofday)(long long res, void *tp_, void *tzp_) {
1018 /* TODO */
1019}
1020PRE_SYSCALL(compat_50_getrusage)(long long who_, void *rusage_) { /* TODO */ }
1021POST_SYSCALL(compat_50_getrusage)
1022(long long res, long long who_, void *rusage_) {
1023 /* TODO */
1024}
1025PRE_SYSCALL(getsockopt)
1026(long long s_, long long level_, long long name_, void *val_, void *avalsize_) {
1027 /* TODO */
1028}
1029POST_SYSCALL(getsockopt)
1030(long long res, long long s_, long long level_, long long name_, void *val_,
1031 void *avalsize_) {
1032 /* TODO */
1033}
1034/* syscall 119 has been skipped */
1035PRE_SYSCALL(readv)(long long fd_, void *iovp_, long long iovcnt_) {
1036 struct __sanitizer_iovec *iovp = (struct __sanitizer_iovec *)iovp_;
1037 int i;
1038 if (iovp) {
1039 PRE_READ(iovp, sizeof(struct __sanitizer_iovec) * iovcnt_);
1040 for (i = 0; i < iovcnt_; i++) {
1041 PRE_WRITE(iovp[i].iov_base, iovp[i].iov_len);
1042 }
1043 }
1044}
1045POST_SYSCALL(readv)
1046(long long res, long long fd_, void *iovp_, long long iovcnt_) {
1047 struct __sanitizer_iovec *iovp = (struct __sanitizer_iovec *)iovp_;
1048 int i;
1049 uptr m, n = res;
1050 if (res > 0) {
1051 if (iovp) {
1052 POST_READ(iovp, sizeof(struct __sanitizer_iovec) * iovcnt_);
1053 for (i = 0; i < iovcnt_ && n > 0; i++) {
1054 m = n > iovp[i].iov_len ? iovp[i].iov_len : n;
1055 POST_WRITE(iovp[i].iov_base, m);
1056 n -= m;
1057 }
1058 }
1059 }
1060}
1061PRE_SYSCALL(writev)(long long fd_, void *iovp_, long long iovcnt_) {
1062 struct __sanitizer_iovec *iovp = (struct __sanitizer_iovec *)iovp_;
1063 int i;
1064 if (iovp) {
1065 PRE_READ(iovp, sizeof(struct __sanitizer_iovec) * iovcnt_);
1066 for (i = 0; i < iovcnt_; i++) {
1067 PRE_READ(iovp[i].iov_base, iovp[i].iov_len);
1068 }
1069 }
1070}
1071POST_SYSCALL(writev)
1072(long long res, long long fd_, void *iovp_, long long iovcnt_) {
1073 struct __sanitizer_iovec *iovp = (struct __sanitizer_iovec *)iovp_;
1074 int i;
1075 uptr m, n = res;
1076 if (res > 0) {
1077 if (iovp) {
1078 POST_READ(iovp, sizeof(struct __sanitizer_iovec) * iovcnt_);
1079 for (i = 0; i < iovcnt_ && n > 0; i++) {
1080 m = n > iovp[i].iov_len ? iovp[i].iov_len : n;
1081 POST_READ(iovp[i].iov_base, m);
1082 n -= m;
1083 }
1084 }
1085 }
1086}
1087PRE_SYSCALL(compat_50_settimeofday)(void *tv_, void *tzp_) { /* TODO */ }
1088POST_SYSCALL(compat_50_settimeofday)(long long res, void *tv_, void *tzp_) {
1089 /* TODO */
1090}
1091PRE_SYSCALL(fchown)(long long fd_, long long uid_, long long gid_) {
1092 /* Nothing to do */
1093}
1094POST_SYSCALL(fchown)
1095(long long res, long long fd_, long long uid_, long long gid_) {
1096 /* Nothing to do */
1097}
1098PRE_SYSCALL(fchmod)(long long fd_, long long mode_) { /* Nothing to do */ }
1099POST_SYSCALL(fchmod)(long long res, long long fd_, long long mode_) {
1100 /* Nothing to do */
1101}
1102PRE_SYSCALL(compat_43_orecvfrom)
1103(long long s_, void *buf_, long long len_, long long flags_, void *from_,
1104 void *fromlenaddr_) {
1105 /* TODO */
1106}
1107POST_SYSCALL(compat_43_orecvfrom)
1108(long long res, long long s_, void *buf_, long long len_, long long flags_,
1109 void *from_, void *fromlenaddr_) {
1110 /* TODO */
1111}
1112PRE_SYSCALL(setreuid)(long long ruid_, long long euid_) { /* Nothing to do */ }
1113POST_SYSCALL(setreuid)(long long res, long long ruid_, long long euid_) {
1114 /* Nothing to do */
1115}
1116PRE_SYSCALL(setregid)(long long rgid_, long long egid_) { /* Nothing to do */ }
1117POST_SYSCALL(setregid)(long long res, long long rgid_, long long egid_) {
1118 /* Nothing to do */
1119}
1120PRE_SYSCALL(rename)(void *from_, void *to_) {
1121 const char *from = (const char *)from_;
1122 const char *to = (const char *)to_;
1123 if (from) {
1124 PRE_READ(from, __sanitizer::internal_strlen(from) + 1);
1125 }
1126 if (to) {
1127 PRE_READ(to, __sanitizer::internal_strlen(to) + 1);
1128 }
1129}
1130POST_SYSCALL(rename)(long long res, void *from_, void *to_) {
1131 if (res == 0) {
1132 const char *from = (const char *)from_;
1133 const char *to = (const char *)to_;
1134 if (from) {
1135 POST_READ(from, __sanitizer::internal_strlen(from) + 1);
1136 }
1137 if (to) {
1138 POST_READ(to, __sanitizer::internal_strlen(to) + 1);
1139 }
1140 }
1141}
1142PRE_SYSCALL(compat_43_otruncate)(void *path_, long long length_) { /* TODO */ }
1143POST_SYSCALL(compat_43_otruncate)
1144(long long res, void *path_, long long length_) {
1145 /* TODO */
1146}
1147PRE_SYSCALL(compat_43_oftruncate)(long long fd_, long long length_) {
1148 /* TODO */
1149}
1150POST_SYSCALL(compat_43_oftruncate)
1151(long long res, long long fd_, long long length_) {
1152 /* TODO */
1153}
1154PRE_SYSCALL(flock)(long long fd_, long long how_) { /* Nothing to do */ }
1155POST_SYSCALL(flock)(long long res, long long fd_, long long how_) {
1156 /* Nothing to do */
1157}
1158PRE_SYSCALL(mkfifo)(void *path_, long long mode_) {
1159 const char *path = (const char *)path_;
1160 if (path) {
1161 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
1162 }
1163}
1164POST_SYSCALL(mkfifo)(long long res, void *path_, long long mode_) {
1165 if (res == 0) {
1166 const char *path = (const char *)path_;
1167 if (path) {
1168 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
1169 }
1170 }
1171}
1172PRE_SYSCALL(sendto)
1173(long long s_, void *buf_, long long len_, long long flags_, void *to_,
1174 long long tolen_) {
1175 PRE_READ(buf_, len_);
1176 PRE_READ(to_, tolen_);
1177}
1178POST_SYSCALL(sendto)
1179(long long res, long long s_, void *buf_, long long len_, long long flags_,
1180 void *to_, long long tolen_) {
1181 if (res >= 0) {
1182 POST_READ(buf_, len_);
1183 POST_READ(to_, tolen_);
1184 }
1185}
1186PRE_SYSCALL(shutdown)(long long s_, long long how_) { /* Nothing to do */ }
1187POST_SYSCALL(shutdown)(long long res, long long s_, long long how_) {
1188 /* Nothing to do */
1189}
1190PRE_SYSCALL(socketpair)
1191(long long domain_, long long type_, long long protocol_, void *rsv_) {
1192 PRE_WRITE(rsv_, 2 * sizeof(int));
1193}
1194POST_SYSCALL(socketpair)
1195(long long res, long long domain_, long long type_, long long protocol_,
1196 void *rsv_) {
1197 if (res == 0) {
1198 POST_WRITE(rsv_, 2 * sizeof(int));
1199 }
1200}
1201PRE_SYSCALL(mkdir)(void *path_, long long mode_) {
1202 const char *path = (const char *)path_;
1203 if (path) {
1204 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
1205 }
1206}
1207POST_SYSCALL(mkdir)(long long res, void *path_, long long mode_) {
1208 if (res == 0) {
1209 const char *path = (const char *)path_;
1210 if (path) {
1211 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
1212 }
1213 }
1214}
1215PRE_SYSCALL(rmdir)(void *path_) {
1216 const char *path = (const char *)path_;
1217 if (path) {
1218 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
1219 }
1220}
1221POST_SYSCALL(rmdir)(long long res, void *path_) {
1222 if (res == 0) {
1223 const char *path = (const char *)path_;
1224 if (path) {
1225 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
1226 }
1227 }
1228}
1229PRE_SYSCALL(compat_50_utimes)(void *path_, void *tptr_) { /* TODO */ }
1230POST_SYSCALL(compat_50_utimes)(long long res, void *path_, void *tptr_) {
1231 /* TODO */
1232}
1233/* syscall 139 has been skipped */
1234PRE_SYSCALL(compat_50_adjtime)(void *delta_, void *olddelta_) { /* TODO */ }
1235POST_SYSCALL(compat_50_adjtime)(long long res, void *delta_, void *olddelta_) {
1236 /* TODO */
1237}
1238PRE_SYSCALL(compat_43_ogetpeername)(long long fdes_, void *asa_, void *alen_) {
1239 /* TODO */
1240}
1241POST_SYSCALL(compat_43_ogetpeername)
1242(long long res, long long fdes_, void *asa_, void *alen_) {
1243 /* TODO */
1244}
1245PRE_SYSCALL(compat_43_ogethostid)(void) { /* TODO */ }
1246POST_SYSCALL(compat_43_ogethostid)(long long res) { /* TODO */ }
1247PRE_SYSCALL(compat_43_osethostid)(long long hostid_) { /* TODO */ }
1248POST_SYSCALL(compat_43_osethostid)(long long res, long long hostid_) {
1249 /* TODO */
1250}
1251PRE_SYSCALL(compat_43_ogetrlimit)(long long which_, void *rlp_) { /* TODO */ }
1252POST_SYSCALL(compat_43_ogetrlimit)
1253(long long res, long long which_, void *rlp_) {
1254 /* TODO */
1255}
1256PRE_SYSCALL(compat_43_osetrlimit)(long long which_, void *rlp_) { /* TODO */ }
1257POST_SYSCALL(compat_43_osetrlimit)
1258(long long res, long long which_, void *rlp_) {
1259 /* TODO */
1260}
1261PRE_SYSCALL(compat_43_okillpg)(long long pgid_, long long signum_) {
1262 /* TODO */
1263}
1264POST_SYSCALL(compat_43_okillpg)
1265(long long res, long long pgid_, long long signum_) {
1266 /* TODO */
1267}
1268PRE_SYSCALL(setsid)(void) { /* Nothing to do */ }
1269POST_SYSCALL(setsid)(long long res) { /* Nothing to do */ }
1270PRE_SYSCALL(compat_50_quotactl)
1271(void *path_, long long cmd_, long long uid_, void *arg_) {
1272 /* TODO */
1273}
1274POST_SYSCALL(compat_50_quotactl)
1275(long long res, void *path_, long long cmd_, long long uid_, void *arg_) {
1276 /* TODO */
1277}
1278PRE_SYSCALL(compat_43_oquota)(void) { /* TODO */ }
1279POST_SYSCALL(compat_43_oquota)(long long res) { /* TODO */ }
1280PRE_SYSCALL(compat_43_ogetsockname)(long long fdec_, void *asa_, void *alen_) {
1281 /* TODO */
1282}
1283POST_SYSCALL(compat_43_ogetsockname)
1284(long long res, long long fdec_, void *asa_, void *alen_) {
1285 /* TODO */
1286}
1287/* syscall 151 has been skipped */
1288/* syscall 152 has been skipped */
1289/* syscall 153 has been skipped */
1290/* syscall 154 has been skipped */
1291PRE_SYSCALL(nfssvc)(long long flag_, void *argp_) { /* Nothing to do */ }
1292POST_SYSCALL(nfssvc)(long long res, long long flag_, void *argp_) {
1293 /* Nothing to do */
1294}
1295PRE_SYSCALL(compat_43_ogetdirentries)
1296(long long fd_, void *buf_, long long count_, void *basep_) {
1297 /* TODO */
1298}
1299POST_SYSCALL(compat_43_ogetdirentries)
1300(long long res, long long fd_, void *buf_, long long count_, void *basep_) {
1301 /* TODO */
1302}
1303PRE_SYSCALL(compat_20_statfs)(void *path_, void *buf_) { /* TODO */ }
1304POST_SYSCALL(compat_20_statfs)(long long res, void *path_, void *buf_) {
1305 /* TODO */
1306}
1307PRE_SYSCALL(compat_20_fstatfs)(long long fd_, void *buf_) { /* TODO */ }
1308POST_SYSCALL(compat_20_fstatfs)(long long res, long long fd_, void *buf_) {
1309 /* TODO */
1310}
1311/* syscall 159 has been skipped */
1312/* syscall 160 has been skipped */
1313PRE_SYSCALL(compat_30_getfh)(void *fname_, void *fhp_) { /* TODO */ }
1314POST_SYSCALL(compat_30_getfh)(long long res, void *fname_, void *fhp_) {
1315 /* TODO */
1316}
1317PRE_SYSCALL(compat_09_ogetdomainname)(void *domainname_, long long len_) {
1318 /* TODO */
1319}
1320POST_SYSCALL(compat_09_ogetdomainname)
1321(long long res, void *domainname_, long long len_) {
1322 /* TODO */
1323}
1324PRE_SYSCALL(compat_09_osetdomainname)(void *domainname_, long long len_) {
1325 /* TODO */
1326}
1327POST_SYSCALL(compat_09_osetdomainname)
1328(long long res, void *domainname_, long long len_) {
1329 /* TODO */
1330}
1331PRE_SYSCALL(compat_09_ouname)(void *name_) { /* TODO */ }
1332POST_SYSCALL(compat_09_ouname)(long long res, void *name_) { /* TODO */ }
1333PRE_SYSCALL(sysarch)(long long op_, void *parms_) { /* TODO */ }
1334POST_SYSCALL(sysarch)(long long res, long long op_, void *parms_) { /* TODO */ }
1335/* syscall 166 has been skipped */
1336/* syscall 167 has been skipped */
1337/* syscall 168 has been skipped */
1338#if !defined(_LP64)
1339PRE_SYSCALL(compat_10_osemsys)
1340(long long which_, long long a2_, long long a3_, long long a4_, long long a5_) {
1341 /* TODO */
1342}
1343POST_SYSCALL(compat_10_osemsys)
1344(long long res, long long which_, long long a2_, long long a3_, long long a4_,
1345 long long a5_) {
1346 /* TODO */
1347}
1348#else
1349/* syscall 169 has been skipped */
1350#endif
1351#if !defined(_LP64)
1352PRE_SYSCALL(compat_10_omsgsys)
1353(long long which_, long long a2_, long long a3_, long long a4_, long long a5_,
1354 long long a6_) {
1355 /* TODO */
1356}
1357POST_SYSCALL(compat_10_omsgsys)
1358(long long res, long long which_, long long a2_, long long a3_, long long a4_,
1359 long long a5_, long long a6_) {
1360 /* TODO */
1361}
1362#else
1363/* syscall 170 has been skipped */
1364#endif
1365#if !defined(_LP64)
1366PRE_SYSCALL(compat_10_oshmsys)
1367(long long which_, long long a2_, long long a3_, long long a4_) {
1368 /* TODO */
1369}
1370POST_SYSCALL(compat_10_oshmsys)
1371(long long res, long long which_, long long a2_, long long a3_, long long a4_) {
1372 /* TODO */
1373}
1374#else
1375/* syscall 171 has been skipped */
1376#endif
1377/* syscall 172 has been skipped */
1378PRE_SYSCALL(pread)
1379(long long fd_, void *buf_, long long nbyte_, long long PAD_,
1380 long long offset_) {
1381 if (buf_) {
1382 PRE_WRITE(buf_, nbyte_);
1383 }
1384}
1385POST_SYSCALL(pread)
1386(long long res, long long fd_, void *buf_, long long nbyte_, long long PAD_,
1387 long long offset_) {
1388 if (res > 0) {
1389 POST_WRITE(buf_, res);
1390 }
1391}
1392PRE_SYSCALL(pwrite)
1393(long long fd_, void *buf_, long long nbyte_, long long PAD_,
1394 long long offset_) {
1395 if (buf_) {
1396 PRE_READ(buf_, nbyte_);
1397 }
1398}
1399POST_SYSCALL(pwrite)
1400(long long res, long long fd_, void *buf_, long long nbyte_, long long PAD_,
1401 long long offset_) {
1402 if (res > 0) {
1403 POST_READ(buf_, res);
1404 }
1405}
1406PRE_SYSCALL(compat_30_ntp_gettime)(void *ntvp_) { /* TODO */ }
1407POST_SYSCALL(compat_30_ntp_gettime)(long long res, void *ntvp_) { /* TODO */ }
1408#if defined(NTP) || !defined(_KERNEL_OPT)
1409PRE_SYSCALL(ntp_adjtime)(void *tp_) { /* Nothing to do */ }
1410POST_SYSCALL(ntp_adjtime)(long long res, void *tp_) { /* Nothing to do */ }
1411#else
1412/* syscall 176 has been skipped */
1413#endif
1414/* syscall 177 has been skipped */
1415/* syscall 178 has been skipped */
1416/* syscall 179 has been skipped */
1417/* syscall 180 has been skipped */
1418PRE_SYSCALL(setgid)(long long gid_) { /* Nothing to do */ }
1419POST_SYSCALL(setgid)(long long res, long long gid_) { /* Nothing to do */ }
1420PRE_SYSCALL(setegid)(long long egid_) { /* Nothing to do */ }
1421POST_SYSCALL(setegid)(long long res, long long egid_) { /* Nothing to do */ }
1422PRE_SYSCALL(seteuid)(long long euid_) { /* Nothing to do */ }
1423POST_SYSCALL(seteuid)(long long res, long long euid_) { /* Nothing to do */ }
1424PRE_SYSCALL(lfs_bmapv)(void *fsidp_, void *blkiov_, long long blkcnt_) {
1425 /* TODO */
1426}
1427POST_SYSCALL(lfs_bmapv)
1428(long long res, void *fsidp_, void *blkiov_, long long blkcnt_) {
1429 /* TODO */
1430}
1431PRE_SYSCALL(lfs_markv)(void *fsidp_, void *blkiov_, long long blkcnt_) {
1432 /* TODO */
1433}
1434POST_SYSCALL(lfs_markv)
1435(long long res, void *fsidp_, void *blkiov_, long long blkcnt_) {
1436 /* TODO */
1437}
1438PRE_SYSCALL(lfs_segclean)(void *fsidp_, long long segment_) { /* TODO */ }
1439POST_SYSCALL(lfs_segclean)(long long res, void *fsidp_, long long segment_) {
1440 /* TODO */
1441}
1442PRE_SYSCALL(compat_50_lfs_segwait)(void *fsidp_, void *tv_) { /* TODO */ }
1443POST_SYSCALL(compat_50_lfs_segwait)(long long res, void *fsidp_, void *tv_) {
1444 /* TODO */
1445}
1446PRE_SYSCALL(compat_12_stat12)(void *path_, void *ub_) { /* TODO */ }
1447POST_SYSCALL(compat_12_stat12)(long long res, void *path_, void *ub_) {
1448 /* TODO */
1449}
1450PRE_SYSCALL(compat_12_fstat12)(long long fd_, void *sb_) { /* TODO */ }
1451POST_SYSCALL(compat_12_fstat12)(long long res, long long fd_, void *sb_) {
1452 /* TODO */
1453}
1454PRE_SYSCALL(compat_12_lstat12)(void *path_, void *ub_) { /* TODO */ }
1455POST_SYSCALL(compat_12_lstat12)(long long res, void *path_, void *ub_) {
1456 /* TODO */
1457}
1458PRE_SYSCALL(pathconf)(void *path_, long long name_) {
1459 const char *path = (const char *)path_;
1460 if (path) {
1461 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
1462 }
1463}
1464POST_SYSCALL(pathconf)(long long res, void *path_, long long name_) {
1465 if (res != -1) {
1466 const char *path = (const char *)path_;
1467 if (path) {
1468 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
1469 }
1470 }
1471}
1472PRE_SYSCALL(fpathconf)(long long fd_, long long name_) { /* Nothing to do */ }
1473POST_SYSCALL(fpathconf)(long long res, long long fd_, long long name_) {
1474 /* Nothing to do */
1475}
1476PRE_SYSCALL(getsockopt2)
1477(long long s_, long long level_, long long name_, void *val_, void *avalsize_) {
1478 /* TODO */
1479}
1480POST_SYSCALL(getsockopt2)
1481(long long res, long long s_, long long level_, long long name_, void *val_,
1482 void *avalsize_) {
1483 /* TODO */
1484}
1485PRE_SYSCALL(getrlimit)(long long which_, void *rlp_) {
1486 PRE_WRITE(rlp_, struct_rlimit_sz);
1487}
1488POST_SYSCALL(getrlimit)(long long res, long long which_, void *rlp_) {
1489 if (res == 0) {
1490 POST_WRITE(rlp_, struct_rlimit_sz);
1491 }
1492}
1493PRE_SYSCALL(setrlimit)(long long which_, void *rlp_) {
1494 PRE_READ(rlp_, struct_rlimit_sz);
1495}
1496POST_SYSCALL(setrlimit)(long long res, long long which_, void *rlp_) {
1497 if (res == 0) {
1498 POST_READ(rlp_, struct_rlimit_sz);
1499 }
1500}
1501PRE_SYSCALL(compat_12_getdirentries)
1502(long long fd_, void *buf_, long long count_, void *basep_) {
1503 /* TODO */
1504}
1505POST_SYSCALL(compat_12_getdirentries)
1506(long long res, long long fd_, void *buf_, long long count_, void *basep_) {
1507 /* TODO */
1508}
1509PRE_SYSCALL(mmap)
1510(void *addr_, long long len_, long long prot_, long long flags_, long long fd_,
1511 long long PAD_, long long pos_) {
1512 /* Nothing to do */
1513}
1514POST_SYSCALL(mmap)
1515(long long res, void *addr_, long long len_, long long prot_, long long flags_,
1516 long long fd_, long long PAD_, long long pos_) {
1517 /* Nothing to do */
1518}
1519PRE_SYSCALL(__syscall)(long long code_, long long args_[SYS_MAXSYSARGS]) {
1520 /* Nothing to do */
1521}
1522POST_SYSCALL(__syscall)
1523(long long res, long long code_, long long args_[SYS_MAXSYSARGS]) {
1524 /* Nothing to do */
1525}
1526PRE_SYSCALL(lseek)
1527(long long fd_, long long PAD_, long long offset_, long long whence_) {
1528 /* Nothing to do */
1529}
1530POST_SYSCALL(lseek)
1531(long long res, long long fd_, long long PAD_, long long offset_,
1532 long long whence_) {
1533 /* Nothing to do */
1534}
1535PRE_SYSCALL(truncate)(void *path_, long long PAD_, long long length_) {
1536 const char *path = (const char *)path_;
1537 if (path) {
1538 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
1539 }
1540}
1541POST_SYSCALL(truncate)
1542(long long res, void *path_, long long PAD_, long long length_) {
1543 if (res == 0) {
1544 const char *path = (const char *)path_;
1545 if (path) {
1546 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
1547 }
1548 }
1549}
1550PRE_SYSCALL(ftruncate)(long long fd_, long long PAD_, long long length_) {
1551 /* Nothing to do */
1552}
1553POST_SYSCALL(ftruncate)
1554(long long res, long long fd_, long long PAD_, long long length_) {
1555 /* Nothing to do */
1556}
1557PRE_SYSCALL(__sysctl)
1558(void *name_, long long namelen_, void *oldv_, void *oldlenp_, void *newv_,
1559 long long newlen_) {
1560 const int *name = (const int *)name_;
1561 if (name) {
1562 PRE_READ(name, namelen_ * sizeof(*name));
1563 }
1564 if (newv_) {
1565 PRE_READ(name, newlen_);
1566 }
1567}
1568POST_SYSCALL(__sysctl)
1569(long long res, void *name_, long long namelen_, void *oldv_, void *oldlenp_,
1570 void *newv_, long long newlen_) {
1571 if (res == 0) {
1572 const int *name = (const int *)name_;
1573 if (name) {
1574 POST_READ(name, namelen_ * sizeof(*name));
1575 }
1576 if (newv_) {
1577 POST_READ(name, newlen_);
1578 }
1579 }
1580}
1581PRE_SYSCALL(mlock)(void *addr_, long long len_) { /* Nothing to do */ }
1582POST_SYSCALL(mlock)(long long res, void *addr_, long long len_) {
1583 /* Nothing to do */
1584}
1585PRE_SYSCALL(munlock)(void *addr_, long long len_) { /* Nothing to do */ }
1586POST_SYSCALL(munlock)(long long res, void *addr_, long long len_) {
1587 /* Nothing to do */
1588}
1589PRE_SYSCALL(undelete)(void *path_) {
1590 const char *path = (const char *)path_;
1591 if (path) {
1592 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
1593 }
1594}
1595POST_SYSCALL(undelete)(long long res, void *path_) {
1596 if (res == 0) {
1597 const char *path = (const char *)path_;
1598 if (path) {
1599 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
1600 }
1601 }
1602}
1603PRE_SYSCALL(compat_50_futimes)(long long fd_, void *tptr_) { /* TODO */ }
1604POST_SYSCALL(compat_50_futimes)(long long res, long long fd_, void *tptr_) {
1605 /* TODO */
1606}
1607PRE_SYSCALL(getpgid)(long long pid_) { /* Nothing to do */ }
1608POST_SYSCALL(getpgid)(long long res, long long pid_) { /* Nothing to do */ }
1609PRE_SYSCALL(reboot)(long long opt_, void *bootstr_) {
1610 const char *bootstr = (const char *)bootstr_;
1611 if (bootstr) {
1612 PRE_READ(bootstr, __sanitizer::internal_strlen(bootstr) + 1);
1613 }
1614}
1615POST_SYSCALL(reboot)(long long res, long long opt_, void *bootstr_) {
1616 /* This call should never return */
1617 const char *bootstr = (const char *)bootstr_;
1618 if (bootstr) {
1619 POST_READ(bootstr, __sanitizer::internal_strlen(bootstr) + 1);
1620 }
1621}
1622PRE_SYSCALL(poll)(void *fds_, long long nfds_, long long timeout_) {
1623 /* Nothing to do */
1624}
1625POST_SYSCALL(poll)
1626(long long res, void *fds_, long long nfds_, long long timeout_) {
1627 /* Nothing to do */
1628}
1629PRE_SYSCALL(afssys)
1630(long long id_, long long a1_, long long a2_, long long a3_, long long a4_,
1631 long long a5_, long long a6_) {
1632 /* TODO */
1633}
1634POST_SYSCALL(afssys)
1635(long long res, long long id_, long long a1_, long long a2_, long long a3_,
1636 long long a4_, long long a5_, long long a6_) {
1637 /* TODO */
1638}
1639/* syscall 211 has been skipped */
1640/* syscall 212 has been skipped */
1641/* syscall 213 has been skipped */
1642/* syscall 214 has been skipped */
1643/* syscall 215 has been skipped */
1644/* syscall 216 has been skipped */
1645/* syscall 217 has been skipped */
1646/* syscall 218 has been skipped */
1647/* syscall 219 has been skipped */
1648PRE_SYSCALL(compat_14___semctl)
1649(long long semid_, long long semnum_, long long cmd_, void *arg_) {
1650 /* TODO */
1651}
1652POST_SYSCALL(compat_14___semctl)
1653(long long res, long long semid_, long long semnum_, long long cmd_,
1654 void *arg_) {
1655 /* TODO */
1656}
1657PRE_SYSCALL(semget)(long long key_, long long nsems_, long long semflg_) {
1658 /* Nothing to do */
1659}
1660POST_SYSCALL(semget)
1661(long long res, long long key_, long long nsems_, long long semflg_) {
1662 /* Nothing to do */
1663}
1664PRE_SYSCALL(semop)(long long semid_, void *sops_, long long nsops_) {
1665 if (sops_) {
1666 PRE_READ(sops_, nsops_ * struct_sembuf_sz);
1667 }
1668}
1669POST_SYSCALL(semop)
1670(long long res, long long semid_, void *sops_, long long nsops_) {
1671 if (res == 0) {
1672 if (sops_) {
1673 POST_READ(sops_, nsops_ * struct_sembuf_sz);
1674 }
1675 }
1676}
1677PRE_SYSCALL(semconfig)(long long flag_) { /* Nothing to do */ }
1678POST_SYSCALL(semconfig)(long long res, long long flag_) { /* Nothing to do */ }
1679PRE_SYSCALL(compat_14_msgctl)(long long msqid_, long long cmd_, void *buf_) {
1680 /* TODO */
1681}
1682POST_SYSCALL(compat_14_msgctl)
1683(long long res, long long msqid_, long long cmd_, void *buf_) {
1684 /* TODO */
1685}
1686PRE_SYSCALL(msgget)(long long key_, long long msgflg_) { /* Nothing to do */ }
1687POST_SYSCALL(msgget)(long long res, long long key_, long long msgflg_) {
1688 /* Nothing to do */
1689}
1690PRE_SYSCALL(msgsnd)
1691(long long msqid_, void *msgp_, long long msgsz_, long long msgflg_) {
1692 if (msgp_) {
1693 PRE_READ(msgp_, msgsz_);
1694 }
1695}
1696POST_SYSCALL(msgsnd)
1697(long long res, long long msqid_, void *msgp_, long long msgsz_,
1698 long long msgflg_) {
1699 if (res == 0) {
1700 if (msgp_) {
1701 POST_READ(msgp_, msgsz_);
1702 }
1703 }
1704}
1705PRE_SYSCALL(msgrcv)
1706(long long msqid_, void *msgp_, long long msgsz_, long long msgtyp_,
1707 long long msgflg_) {
1708 /* Nothing to do */
1709}
1710POST_SYSCALL(msgrcv)
1711(long long res, long long msqid_, void *msgp_, long long msgsz_,
1712 long long msgtyp_, long long msgflg_) {
1713 /* Nothing to do */
1714}
1715PRE_SYSCALL(shmat)(long long shmid_, void *shmaddr_, long long shmflg_) {
1716 /* Nothing to do */
1717}
1718POST_SYSCALL(shmat)
1719(long long res, long long shmid_, void *shmaddr_, long long shmflg_) {
1720 /* Nothing to do */
1721}
1722PRE_SYSCALL(compat_14_shmctl)(long long shmid_, long long cmd_, void *buf_) {
1723 /* TODO */
1724}
1725POST_SYSCALL(compat_14_shmctl)
1726(long long res, long long shmid_, long long cmd_, void *buf_) {
1727 /* TODO */
1728}
1729PRE_SYSCALL(shmdt)(void *shmaddr_) { /* Nothing to do */ }
1730POST_SYSCALL(shmdt)(long long res, void *shmaddr_) { /* Nothing to do */ }
1731PRE_SYSCALL(shmget)(long long key_, long long size_, long long shmflg_) {
1732 /* Nothing to do */
1733}
1734POST_SYSCALL(shmget)
1735(long long res, long long key_, long long size_, long long shmflg_) {
1736 /* Nothing to do */
1737}
1738PRE_SYSCALL(compat_50_clock_gettime)(long long clock_id_, void *tp_) {
1739 /* TODO */
1740}
1741POST_SYSCALL(compat_50_clock_gettime)
1742(long long res, long long clock_id_, void *tp_) {
1743 /* TODO */
1744}
1745PRE_SYSCALL(compat_50_clock_settime)(long long clock_id_, void *tp_) {
1746 /* TODO */
1747}
1748POST_SYSCALL(compat_50_clock_settime)
1749(long long res, long long clock_id_, void *tp_) {
1750 /* TODO */
1751}
1752PRE_SYSCALL(compat_50_clock_getres)(long long clock_id_, void *tp_) {
1753 /* TODO */
1754}
1755POST_SYSCALL(compat_50_clock_getres)
1756(long long res, long long clock_id_, void *tp_) {
1757 /* TODO */
1758}
1759PRE_SYSCALL(timer_create)(long long clock_id_, void *evp_, void *timerid_) {
1760 /* Nothing to do */
1761}
1762POST_SYSCALL(timer_create)
1763(long long res, long long clock_id_, void *evp_, void *timerid_) {
1764 /* Nothing to do */
1765}
1766PRE_SYSCALL(timer_delete)(long long timerid_) { /* Nothing to do */ }
1767POST_SYSCALL(timer_delete)(long long res, long long timerid_) {
1768 /* Nothing to do */
1769}
1770PRE_SYSCALL(compat_50_timer_settime)
1771(long long timerid_, long long flags_, void *value_, void *ovalue_) {
1772 /* TODO */
1773}
1774POST_SYSCALL(compat_50_timer_settime)
1775(long long res, long long timerid_, long long flags_, void *value_,
1776 void *ovalue_) {
1777 /* TODO */
1778}
1779PRE_SYSCALL(compat_50_timer_gettime)(long long timerid_, void *value_) {
1780 /* TODO */
1781}
1782POST_SYSCALL(compat_50_timer_gettime)
1783(long long res, long long timerid_, void *value_) {
1784 /* TODO */
1785}
1786PRE_SYSCALL(timer_getoverrun)(long long timerid_) { /* Nothing to do */ }
1787POST_SYSCALL(timer_getoverrun)(long long res, long long timerid_) {
1788 /* Nothing to do */
1789}
1790PRE_SYSCALL(compat_50_nanosleep)(void *rqtp_, void *rmtp_) { /* TODO */ }
1791POST_SYSCALL(compat_50_nanosleep)(long long res, void *rqtp_, void *rmtp_) {
1792 /* TODO */
1793}
1794PRE_SYSCALL(fdatasync)(long long fd_) { /* Nothing to do */ }
1795POST_SYSCALL(fdatasync)(long long res, long long fd_) { /* Nothing to do */ }
1796PRE_SYSCALL(mlockall)(long long flags_) { /* Nothing to do */ }
1797POST_SYSCALL(mlockall)(long long res, long long flags_) { /* Nothing to do */ }
1798PRE_SYSCALL(munlockall)(void) { /* Nothing to do */ }
1799POST_SYSCALL(munlockall)(long long res) { /* Nothing to do */ }
1800PRE_SYSCALL(compat_50___sigtimedwait)(void *set_, void *info_, void *timeout_) {
1801 /* TODO */
1802}
1803POST_SYSCALL(compat_50___sigtimedwait)
1804(long long res, void *set_, void *info_, void *timeout_) {
1805 /* TODO */
1806}
1807PRE_SYSCALL(sigqueueinfo)(long long pid_, void *info_) {
1808 if (info_) {
1809 PRE_READ(info_, siginfo_t_sz);
1810 }
1811}
1812POST_SYSCALL(sigqueueinfo)(long long res, long long pid_, void *info_) {}
1813PRE_SYSCALL(modctl)(long long cmd_, void *arg_) { /* TODO */ }
1814POST_SYSCALL(modctl)(long long res, long long cmd_, void *arg_) { /* TODO */ }
1815PRE_SYSCALL(_ksem_init)(long long value_, void *idp_) { /* Nothing to do */ }
1816POST_SYSCALL(_ksem_init)(long long res, long long value_, void *idp_) {
1817 /* Nothing to do */
1818}
1819PRE_SYSCALL(_ksem_open)
1820(void *name_, long long oflag_, long long mode_, long long value_, void *idp_) {
1821 const char *name = (const char *)name_;
1822 if (name) {
1823 PRE_READ(name, __sanitizer::internal_strlen(name) + 1);
1824 }
1825}
1826POST_SYSCALL(_ksem_open)
1827(long long res, void *name_, long long oflag_, long long mode_,
1828 long long value_, void *idp_) {
1829 const char *name = (const char *)name_;
1830 if (name) {
1831 POST_READ(name, __sanitizer::internal_strlen(name) + 1);
1832 }
1833}
1834PRE_SYSCALL(_ksem_unlink)(void *name_) {
1835 const char *name = (const char *)name_;
1836 if (name) {
1837 PRE_READ(name, __sanitizer::internal_strlen(name) + 1);
1838 }
1839}
1840POST_SYSCALL(_ksem_unlink)(long long res, void *name_) {
1841 const char *name = (const char *)name_;
1842 if (name) {
1843 POST_READ(name, __sanitizer::internal_strlen(name) + 1);
1844 }
1845}
1846PRE_SYSCALL(_ksem_close)(long long id_) { /* Nothing to do */ }
1847POST_SYSCALL(_ksem_close)(long long res, long long id_) { /* Nothing to do */ }
1848PRE_SYSCALL(_ksem_post)(long long id_) { /* Nothing to do */ }
1849POST_SYSCALL(_ksem_post)(long long res, long long id_) { /* Nothing to do */ }
1850PRE_SYSCALL(_ksem_wait)(long long id_) { /* Nothing to do */ }
1851POST_SYSCALL(_ksem_wait)(long long res, long long id_) { /* Nothing to do */ }
1852PRE_SYSCALL(_ksem_trywait)(long long id_) { /* Nothing to do */ }
1853POST_SYSCALL(_ksem_trywait)(long long res, long long id_) {
1854 /* Nothing to do */
1855}
1856PRE_SYSCALL(_ksem_getvalue)(long long id_, void *value_) { /* Nothing to do */ }
1857POST_SYSCALL(_ksem_getvalue)(long long res, long long id_, void *value_) {
1858 /* Nothing to do */
1859}
1860PRE_SYSCALL(_ksem_destroy)(long long id_) { /* Nothing to do */ }
1861POST_SYSCALL(_ksem_destroy)(long long res, long long id_) {
1862 /* Nothing to do */
1863}
1864PRE_SYSCALL(_ksem_timedwait)(long long id_, void *abstime_) {
1865 if (abstime_) {
1866 PRE_READ(abstime_, struct_timespec_sz);
1867 }
1868}
1869POST_SYSCALL(_ksem_timedwait)(long long res, long long id_, void *abstime_) {}
1870PRE_SYSCALL(mq_open)
1871(void *name_, long long oflag_, long long mode_, void *attr_) {
1872 const char *name = (const char *)name_;
1873 if (name) {
1874 PRE_READ(name, __sanitizer::internal_strlen(name) + 1);
1875 }
1876}
1877POST_SYSCALL(mq_open)
1878(long long res, void *name_, long long oflag_, long long mode_, void *attr_) {
1879 const char *name = (const char *)name_;
1880 if (name) {
1881 POST_READ(name, __sanitizer::internal_strlen(name) + 1);
1882 }
1883}
1884PRE_SYSCALL(mq_close)(long long mqdes_) { /* Nothing to do */ }
1885POST_SYSCALL(mq_close)(long long res, long long mqdes_) { /* Nothing to do */ }
1886PRE_SYSCALL(mq_unlink)(void *name_) {
1887 const char *name = (const char *)name_;
1888 if (name) {
1889 PRE_READ(name, __sanitizer::internal_strlen(name) + 1);
1890 }
1891}
1892POST_SYSCALL(mq_unlink)(long long res, void *name_) {
1893 const char *name = (const char *)name_;
1894 if (name) {
1895 POST_READ(name, __sanitizer::internal_strlen(name) + 1);
1896 }
1897}
1898PRE_SYSCALL(mq_getattr)(long long mqdes_, void *mqstat_) { /* Nothing to do */ }
1899POST_SYSCALL(mq_getattr)(long long res, long long mqdes_, void *mqstat_) {
1900 /* Nothing to do */
1901}
1902PRE_SYSCALL(mq_setattr)(long long mqdes_, void *mqstat_, void *omqstat_) {
1903 if (mqstat_) {
1904 PRE_READ(mqstat_, struct_mq_attr_sz);
1905 }
1906}
1907POST_SYSCALL(mq_setattr)
1908(long long res, long long mqdes_, void *mqstat_, void *omqstat_) {}
1909PRE_SYSCALL(mq_notify)(long long mqdes_, void *notification_) {
1910 if (notification_) {
1911 PRE_READ(notification_, struct_sigevent_sz);
1912 }
1913}
1914POST_SYSCALL(mq_notify)(long long res, long long mqdes_, void *notification_) {}
1915PRE_SYSCALL(mq_send)
1916(long long mqdes_, void *msg_ptr_, long long msg_len_, long long msg_prio_) {
1917 if (msg_ptr_) {
1918 PRE_READ(msg_ptr_, msg_len_);
1919 }
1920}
1921POST_SYSCALL(mq_send)
1922(long long res, long long mqdes_, void *msg_ptr_, long long msg_len_,
1923 long long msg_prio_) {}
1924PRE_SYSCALL(mq_receive)
1925(long long mqdes_, void *msg_ptr_, long long msg_len_, void *msg_prio_) {
1926 /* Nothing to do */
1927}
1928POST_SYSCALL(mq_receive)
1929(long long res, long long mqdes_, void *msg_ptr_, long long msg_len_,
1930 void *msg_prio_) {
1931 /* Nothing to do */
1932}
1933PRE_SYSCALL(compat_50_mq_timedsend)
1934(long long mqdes_, void *msg_ptr_, long long msg_len_, long long msg_prio_,
1935 void *abs_timeout_) {
1936 /* TODO */
1937}
1938POST_SYSCALL(compat_50_mq_timedsend)
1939(long long res, long long mqdes_, void *msg_ptr_, long long msg_len_,
1940 long long msg_prio_, void *abs_timeout_) {
1941 /* TODO */
1942}
1943PRE_SYSCALL(compat_50_mq_timedreceive)
1944(long long mqdes_, void *msg_ptr_, long long msg_len_, void *msg_prio_,
1945 void *abs_timeout_) {
1946 /* TODO */
1947}
1948POST_SYSCALL(compat_50_mq_timedreceive)
1949(long long res, long long mqdes_, void *msg_ptr_, long long msg_len_,
1950 void *msg_prio_, void *abs_timeout_) {
1951 /* TODO */
1952}
1953/* syscall 267 has been skipped */
1954/* syscall 268 has been skipped */
1955/* syscall 269 has been skipped */
1956PRE_SYSCALL(__posix_rename)(void *from_, void *to_) {
1957 const char *from = (const char *)from_;
1958 const char *to = (const char *)to_;
1959 if (from_) {
1960 PRE_READ(from, __sanitizer::internal_strlen(from) + 1);
1961 }
1962 if (to) {
1963 PRE_READ(to, __sanitizer::internal_strlen(to) + 1);
1964 }
1965}
1966POST_SYSCALL(__posix_rename)(long long res, void *from_, void *to_) {
1967 const char *from = (const char *)from_;
1968 const char *to = (const char *)to_;
1969 if (from) {
1970 POST_READ(from, __sanitizer::internal_strlen(from) + 1);
1971 }
1972 if (to) {
1973 POST_READ(to, __sanitizer::internal_strlen(to) + 1);
1974 }
1975}
1976PRE_SYSCALL(swapctl)(long long cmd_, void *arg_, long long misc_) { /* TODO */ }
1977POST_SYSCALL(swapctl)
1978(long long res, long long cmd_, void *arg_, long long misc_) {
1979 /* TODO */
1980}
1981PRE_SYSCALL(compat_30_getdents)(long long fd_, void *buf_, long long count_) {
1982 /* TODO */
1983}
1984POST_SYSCALL(compat_30_getdents)
1985(long long res, long long fd_, void *buf_, long long count_) {
1986 /* TODO */
1987}
1988PRE_SYSCALL(minherit)(void *addr_, long long len_, long long inherit_) {
1989 /* Nothing to do */
1990}
1991POST_SYSCALL(minherit)
1992(long long res, void *addr_, long long len_, long long inherit_) {
1993 /* Nothing to do */
1994}
1995PRE_SYSCALL(lchmod)(void *path_, long long mode_) {
1996 const char *path = (const char *)path_;
1997 if (path) {
1998 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
1999 }
2000}
2001POST_SYSCALL(lchmod)(long long res, void *path_, long long mode_) {
2002 const char *path = (const char *)path_;
2003 if (path) {
2004 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
2005 }
2006}
2007PRE_SYSCALL(lchown)(void *path_, long long uid_, long long gid_) {
2008 const char *path = (const char *)path_;
2009 if (path) {
2010 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
2011 }
2012}
2013POST_SYSCALL(lchown)
2014(long long res, void *path_, long long uid_, long long gid_) {
2015 const char *path = (const char *)path_;
2016 if (path) {
2017 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
2018 }
2019}
2020PRE_SYSCALL(compat_50_lutimes)(void *path_, void *tptr_) { /* TODO */ }
2021POST_SYSCALL(compat_50_lutimes)(long long res, void *path_, void *tptr_) {
2022 /* TODO */
2023}
2024PRE_SYSCALL(__msync13)(void *addr_, long long len_, long long flags_) {
2025 /* Nothing to do */
2026}
2027POST_SYSCALL(__msync13)
2028(long long res, void *addr_, long long len_, long long flags_) {
2029 /* Nothing to do */
2030}
2031PRE_SYSCALL(compat_30___stat13)(void *path_, void *ub_) { /* TODO */ }
2032POST_SYSCALL(compat_30___stat13)(long long res, void *path_, void *ub_) {
2033 /* TODO */
2034}
2035PRE_SYSCALL(compat_30___fstat13)(long long fd_, void *sb_) { /* TODO */ }
2036POST_SYSCALL(compat_30___fstat13)(long long res, long long fd_, void *sb_) {
2037 /* TODO */
2038}
2039PRE_SYSCALL(compat_30___lstat13)(void *path_, void *ub_) { /* TODO */ }
2040POST_SYSCALL(compat_30___lstat13)(long long res, void *path_, void *ub_) {
2041 /* TODO */
2042}
2043PRE_SYSCALL(__sigaltstack14)(void *nss_, void *oss_) {
2044 if (nss_) {
2045 PRE_READ(nss_, struct_sigaltstack_sz);
2046 }
2047 if (oss_) {
2048 PRE_READ(oss_, struct_sigaltstack_sz);
2049 }
2050}
2051POST_SYSCALL(__sigaltstack14)(long long res, void *nss_, void *oss_) {}
2052PRE_SYSCALL(__vfork14)(void) { /* Nothing to do */ }
2053POST_SYSCALL(__vfork14)(long long res) { /* Nothing to do */ }
2054PRE_SYSCALL(__posix_chown)(void *path_, long long uid_, long long gid_) {
2055 const char *path = (const char *)path_;
2056 if (path) {
2057 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
2058 }
2059}
2060POST_SYSCALL(__posix_chown)
2061(long long res, void *path_, long long uid_, long long gid_) {
2062 const char *path = (const char *)path_;
2063 if (path) {
2064 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
2065 }
2066}
2067PRE_SYSCALL(__posix_fchown)(long long fd_, long long uid_, long long gid_) {
2068 /* Nothing to do */
2069}
2070POST_SYSCALL(__posix_fchown)
2071(long long res, long long fd_, long long uid_, long long gid_) {
2072 /* Nothing to do */
2073}
2074PRE_SYSCALL(__posix_lchown)(void *path_, long long uid_, long long gid_) {
2075 const char *path = (const char *)path_;
2076 if (path) {
2077 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
2078 }
2079}
2080POST_SYSCALL(__posix_lchown)
2081(long long res, void *path_, long long uid_, long long gid_) {
2082 const char *path = (const char *)path_;
2083 if (path) {
2084 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
2085 }
2086}
2087PRE_SYSCALL(getsid)(long long pid_) { /* Nothing to do */ }
2088POST_SYSCALL(getsid)(long long res, long long pid_) { /* Nothing to do */ }
2089PRE_SYSCALL(__clone)(long long flags_, void *stack_) { /* Nothing to do */ }
2090POST_SYSCALL(__clone)(long long res, long long flags_, void *stack_) {
2091 /* Nothing to do */
2092}
2093PRE_SYSCALL(fktrace)
2094(long long fd_, long long ops_, long long facs_, long long pid_) {
2095 /* Nothing to do */
2096}
2097POST_SYSCALL(fktrace)
2098(long long res, long long fd_, long long ops_, long long facs_,
2099 long long pid_) {
2100 /* Nothing to do */
2101}
2102PRE_SYSCALL(preadv)
2103(long long fd_, void *iovp_, long long iovcnt_, long long PAD_,
2104 long long offset_) {
2105 /* Nothing to do */
2106}
2107POST_SYSCALL(preadv)
2108(long long res, long long fd_, void *iovp_, long long iovcnt_, long long PAD_,
2109 long long offset_) {
2110 /* Nothing to do */
2111}
2112PRE_SYSCALL(pwritev)
2113(long long fd_, void *iovp_, long long iovcnt_, long long PAD_,
2114 long long offset_) {
2115 /* Nothing to do */
2116}
2117POST_SYSCALL(pwritev)
2118(long long res, long long fd_, void *iovp_, long long iovcnt_, long long PAD_,
2119 long long offset_) {
2120 /* Nothing to do */
2121}
2122PRE_SYSCALL(compat_16___sigaction14)
2123(long long signum_, void *nsa_, void *osa_) {
2124 /* TODO */
2125}
2126POST_SYSCALL(compat_16___sigaction14)
2127(long long res, long long signum_, void *nsa_, void *osa_) {
2128 /* TODO */
2129}
2130PRE_SYSCALL(__sigpending14)(void *set_) { /* Nothing to do */ }
2131POST_SYSCALL(__sigpending14)(long long res, void *set_) { /* Nothing to do */ }
2132PRE_SYSCALL(__sigprocmask14)(long long how_, void *set_, void *oset_) {
2133 /* Nothing to do */
2134}
2135POST_SYSCALL(__sigprocmask14)
2136(long long res, long long how_, void *set_, void *oset_) {
2137 /* Nothing to do */
2138}
2139PRE_SYSCALL(__sigsuspend14)(void *set_) {
2140 if (set_) {
2141 PRE_READ(set_, sizeof(__sanitizer_sigset_t));
2142 }
2143}
2144POST_SYSCALL(__sigsuspend14)(long long res, void *set_) {
2145 if (set_) {
2146 PRE_READ(set_, sizeof(__sanitizer_sigset_t));
2147 }
2148}
2149PRE_SYSCALL(compat_16___sigreturn14)(void *sigcntxp_) { /* TODO */ }
2150POST_SYSCALL(compat_16___sigreturn14)(long long res, void *sigcntxp_) {
2151 /* TODO */
2152}
2153PRE_SYSCALL(__getcwd)(void *bufp_, long long length_) { /* Nothing to do */ }
2154POST_SYSCALL(__getcwd)(long long res, void *bufp_, long long length_) {
2155 /* Nothing to do */
2156}
2157PRE_SYSCALL(fchroot)(long long fd_) { /* Nothing to do */ }
2158POST_SYSCALL(fchroot)(long long res, long long fd_) { /* Nothing to do */ }
2159PRE_SYSCALL(compat_30_fhopen)(void *fhp_, long long flags_) { /* TODO */ }
2160POST_SYSCALL(compat_30_fhopen)(long long res, void *fhp_, long long flags_) {
2161 /* TODO */
2162}
2163PRE_SYSCALL(compat_30_fhstat)(void *fhp_, void *sb_) { /* TODO */ }
2164POST_SYSCALL(compat_30_fhstat)(long long res, void *fhp_, void *sb_) {
2165 /* TODO */
2166}
2167PRE_SYSCALL(compat_20_fhstatfs)(void *fhp_, void *buf_) { /* TODO */ }
2168POST_SYSCALL(compat_20_fhstatfs)(long long res, void *fhp_, void *buf_) {
2169 /* TODO */
2170}
2171PRE_SYSCALL(compat_50_____semctl13)
2172(long long semid_, long long semnum_, long long cmd_, void *arg_) {
2173 /* TODO */
2174}
2175POST_SYSCALL(compat_50_____semctl13)
2176(long long res, long long semid_, long long semnum_, long long cmd_,
2177 void *arg_) {
2178 /* TODO */
2179}
2180PRE_SYSCALL(compat_50___msgctl13)
2181(long long msqid_, long long cmd_, void *buf_) {
2182 /* TODO */
2183}
2184POST_SYSCALL(compat_50___msgctl13)
2185(long long res, long long msqid_, long long cmd_, void *buf_) {
2186 /* TODO */
2187}
2188PRE_SYSCALL(compat_50___shmctl13)
2189(long long shmid_, long long cmd_, void *buf_) {
2190 /* TODO */
2191}
2192POST_SYSCALL(compat_50___shmctl13)
2193(long long res, long long shmid_, long long cmd_, void *buf_) {
2194 /* TODO */
2195}
2196PRE_SYSCALL(lchflags)(void *path_, long long flags_) {
2197 const char *path = (const char *)path_;
2198 if (path) {
2199 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
2200 }
2201}
2202POST_SYSCALL(lchflags)(long long res, void *path_, long long flags_) {
2203 const char *path = (const char *)path_;
2204 if (path) {
2205 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
2206 }
2207}
2208PRE_SYSCALL(issetugid)(void) { /* Nothing to do */ }
2209POST_SYSCALL(issetugid)(long long res) { /* Nothing to do */ }
2210PRE_SYSCALL(utrace)(void *label_, void *addr_, long long len_) {
2211 const char *label = (const char *)label_;
2212 if (label) {
2213 PRE_READ(label, __sanitizer::internal_strlen(label) + 1);
2214 }
2215 if (addr_) {
2216 PRE_READ(addr_, len_);
2217 }
2218}
2219POST_SYSCALL(utrace)(long long res, void *label_, void *addr_, long long len_) {
2220 const char *label = (const char *)label_;
2221 if (label) {
2222 POST_READ(label, __sanitizer::internal_strlen(label) + 1);
2223 }
2224 if (addr_) {
2225 POST_READ(addr_, len_);
2226 }
2227}
2228PRE_SYSCALL(getcontext)(void *ucp_) { /* Nothing to do */ }
2229POST_SYSCALL(getcontext)(long long res, void *ucp_) { /* Nothing to do */ }
2230PRE_SYSCALL(setcontext)(void *ucp_) {
2231 if (ucp_) {
2232 PRE_READ(ucp_, ucontext_t_sz);
2233 }
2234}
2235POST_SYSCALL(setcontext)(long long res, void *ucp_) {}
2236PRE_SYSCALL(_lwp_create)(void *ucp_, long long flags_, void *new_lwp_) {
2237 if (ucp_) {
2238 PRE_READ(ucp_, ucontext_t_sz);
2239 }
2240}
2241POST_SYSCALL(_lwp_create)
2242(long long res, void *ucp_, long long flags_, void *new_lwp_) {}
2243PRE_SYSCALL(_lwp_exit)(void) { /* Nothing to do */ }
2244POST_SYSCALL(_lwp_exit)(long long res) { /* Nothing to do */ }
2245PRE_SYSCALL(_lwp_self)(void) { /* Nothing to do */ }
2246POST_SYSCALL(_lwp_self)(long long res) { /* Nothing to do */ }
2247PRE_SYSCALL(_lwp_wait)(long long wait_for_, void *departed_) {
2248 /* Nothing to do */
2249}
2250POST_SYSCALL(_lwp_wait)(long long res, long long wait_for_, void *departed_) {
2251 /* Nothing to do */
2252}
2253PRE_SYSCALL(_lwp_suspend)(long long target_) { /* Nothing to do */ }
2254POST_SYSCALL(_lwp_suspend)(long long res, long long target_) {
2255 /* Nothing to do */
2256}
2257PRE_SYSCALL(_lwp_continue)(long long target_) { /* Nothing to do */ }
2258POST_SYSCALL(_lwp_continue)(long long res, long long target_) {
2259 /* Nothing to do */
2260}
2261PRE_SYSCALL(_lwp_wakeup)(long long target_) { /* Nothing to do */ }
2262POST_SYSCALL(_lwp_wakeup)(long long res, long long target_) {
2263 /* Nothing to do */
2264}
2265PRE_SYSCALL(_lwp_getprivate)(void) { /* Nothing to do */ }
2266POST_SYSCALL(_lwp_getprivate)(long long res) { /* Nothing to do */ }
2267PRE_SYSCALL(_lwp_setprivate)(void *ptr_) { /* Nothing to do */ }
2268POST_SYSCALL(_lwp_setprivate)(long long res, void *ptr_) { /* Nothing to do */ }
2269PRE_SYSCALL(_lwp_kill)(long long target_, long long signo_) {
2270 /* Nothing to do */
2271}
2272POST_SYSCALL(_lwp_kill)(long long res, long long target_, long long signo_) {
2273 /* Nothing to do */
2274}
2275PRE_SYSCALL(_lwp_detach)(long long target_) { /* Nothing to do */ }
2276POST_SYSCALL(_lwp_detach)(long long res, long long target_) {
2277 /* Nothing to do */
2278}
2279PRE_SYSCALL(compat_50__lwp_park)
2280(void *ts_, long long unpark_, void *hint_, void *unparkhint_) {
2281 /* TODO */
2282}
2283POST_SYSCALL(compat_50__lwp_park)
2284(long long res, void *ts_, long long unpark_, void *hint_, void *unparkhint_) {
2285 /* TODO */
2286}
2287PRE_SYSCALL(_lwp_unpark)(long long target_, void *hint_) { /* Nothing to do */ }
2288POST_SYSCALL(_lwp_unpark)(long long res, long long target_, void *hint_) {
2289 /* Nothing to do */
2290}
2291PRE_SYSCALL(_lwp_unpark_all)(void *targets_, long long ntargets_, void *hint_) {
2292 if (targets_) {
2293 PRE_READ(targets_, ntargets_ * sizeof(__sanitizer_lwpid_t));
2294 }
2295}
2296POST_SYSCALL(_lwp_unpark_all)
2297(long long res, void *targets_, long long ntargets_, void *hint_) {}
2298PRE_SYSCALL(_lwp_setname)(long long target_, void *name_) {
2299 const char *name = (const char *)name_;
2300 if (name) {
2301 PRE_READ(name, __sanitizer::internal_strlen(name) + 1);
2302 }
2303}
2304POST_SYSCALL(_lwp_setname)(long long res, long long target_, void *name_) {
2305 const char *name = (const char *)name_;
2306 if (name) {
2307 POST_READ(name, __sanitizer::internal_strlen(name) + 1);
2308 }
2309}
2310PRE_SYSCALL(_lwp_getname)(long long target_, void *name_, long long len_) {
2311 /* Nothing to do */
2312}
2313POST_SYSCALL(_lwp_getname)
2314(long long res, long long target_, void *name_, long long len_) {
2315 /* Nothing to do */
2316}
2317PRE_SYSCALL(_lwp_ctl)(long long features_, void **address_) {
2318 /* Nothing to do */
2319}
2320POST_SYSCALL(_lwp_ctl)(long long res, long long features_, void **address_) {
2321 /* Nothing to do */
2322}
2323/* syscall 326 has been skipped */
2324/* syscall 327 has been skipped */
2325/* syscall 328 has been skipped */
2326/* syscall 329 has been skipped */
2327PRE_SYSCALL(compat_60_sa_register)
2328(void *newv_, void **oldv_, long long flags_, long long stackinfo_offset_) {
2329 /* TODO */
2330}
2331POST_SYSCALL(compat_60_sa_register)
2332(long long res, void *newv_, void **oldv_, long long flags_,
2333 long long stackinfo_offset_) {
2334 /* TODO */
2335}
2336PRE_SYSCALL(compat_60_sa_stacks)(long long num_, void *stacks_) { /* TODO */ }
2337POST_SYSCALL(compat_60_sa_stacks)
2338(long long res, long long num_, void *stacks_) {
2339 /* TODO */
2340}
2341PRE_SYSCALL(compat_60_sa_enable)(void) { /* TODO */ }
2342POST_SYSCALL(compat_60_sa_enable)(long long res) { /* TODO */ }
2343PRE_SYSCALL(compat_60_sa_setconcurrency)(long long concurrency_) { /* TODO */ }
2344POST_SYSCALL(compat_60_sa_setconcurrency)
2345(long long res, long long concurrency_) {
2346 /* TODO */
2347}
2348PRE_SYSCALL(compat_60_sa_yield)(void) { /* TODO */ }
2349POST_SYSCALL(compat_60_sa_yield)(long long res) { /* TODO */ }
2350PRE_SYSCALL(compat_60_sa_preempt)(long long sa_id_) { /* TODO */ }
2351POST_SYSCALL(compat_60_sa_preempt)(long long res, long long sa_id_) {
2352 /* TODO */
2353}
2354/* syscall 336 has been skipped */
2355/* syscall 337 has been skipped */
2356/* syscall 338 has been skipped */
2357/* syscall 339 has been skipped */
2358PRE_SYSCALL(__sigaction_sigtramp)
2359(long long signum_, void *nsa_, void *osa_, void *tramp_, long long vers_) {
2360 if (nsa_) {
2361 PRE_READ(nsa_, sizeof(__sanitizer_sigaction));
2362 }
2363}
2364POST_SYSCALL(__sigaction_sigtramp)
2365(long long res, long long signum_, void *nsa_, void *osa_, void *tramp_,
2366 long long vers_) {
2367 if (nsa_) {
2368 PRE_READ(nsa_, sizeof(__sanitizer_sigaction));
2369 }
2370}
2371/* syscall 341 has been skipped */
2372/* syscall 342 has been skipped */
2373PRE_SYSCALL(rasctl)(void *addr_, long long len_, long long op_) {
2374 /* Nothing to do */
2375}
2376POST_SYSCALL(rasctl)
2377(long long res, void *addr_, long long len_, long long op_) {
2378 /* Nothing to do */
2379}
2380PRE_SYSCALL(kqueue)(void) { /* Nothing to do */ }
2381POST_SYSCALL(kqueue)(long long res) { /* Nothing to do */ }
2382PRE_SYSCALL(compat_50_kevent)
2383(long long fd_, void *changelist_, long long nchanges_, void *eventlist_,
2384 long long nevents_, void *timeout_) {
2385 /* TODO */
2386}
2387POST_SYSCALL(compat_50_kevent)
2388(long long res, long long fd_, void *changelist_, long long nchanges_,
2389 void *eventlist_, long long nevents_, void *timeout_) {
2390 /* TODO */
2391}
2392PRE_SYSCALL(_sched_setparam)
2393(long long pid_, long long lid_, long long policy_, void *params_) {
2394 if (params_) {
2395 PRE_READ(params_, struct_sched_param_sz);
2396 }
2397}
2398POST_SYSCALL(_sched_setparam)
2399(long long res, long long pid_, long long lid_, long long policy_,
2400 void *params_) {
2401 if (params_) {
2402 PRE_READ(params_, struct_sched_param_sz);
2403 }
2404}
2405PRE_SYSCALL(_sched_getparam)
2406(long long pid_, long long lid_, void *policy_, void *params_) {
2407 /* Nothing to do */
2408}
2409POST_SYSCALL(_sched_getparam)
2410(long long res, long long pid_, long long lid_, void *policy_, void *params_) {
2411 /* Nothing to do */
2412}
2413PRE_SYSCALL(_sched_setaffinity)
2414(long long pid_, long long lid_, long long size_, void *cpuset_) {
2415 if (cpuset_) {
2416 PRE_READ(cpuset_, size_);
2417 }
2418}
2419POST_SYSCALL(_sched_setaffinity)
2420(long long res, long long pid_, long long lid_, long long size_,
2421 void *cpuset_) {
2422 if (cpuset_) {
2423 PRE_READ(cpuset_, size_);
2424 }
2425}
2426PRE_SYSCALL(_sched_getaffinity)
2427(long long pid_, long long lid_, long long size_, void *cpuset_) {
2428 /* Nothing to do */
2429}
2430POST_SYSCALL(_sched_getaffinity)
2431(long long res, long long pid_, long long lid_, long long size_,
2432 void *cpuset_) {
2433 /* Nothing to do */
2434}
2435PRE_SYSCALL(sched_yield)(void) { /* Nothing to do */ }
2436POST_SYSCALL(sched_yield)(long long res) { /* Nothing to do */ }
2437PRE_SYSCALL(_sched_protect)(long long priority_) { /* Nothing to do */ }
2438POST_SYSCALL(_sched_protect)(long long res, long long priority_) {
2439 /* Nothing to do */
2440}
2441/* syscall 352 has been skipped */
2442/* syscall 353 has been skipped */
2443PRE_SYSCALL(fsync_range)
2444(long long fd_, long long flags_, long long start_, long long length_) {
2445 /* Nothing to do */
2446}
2447POST_SYSCALL(fsync_range)
2448(long long res, long long fd_, long long flags_, long long start_,
2449 long long length_) {
2450 /* Nothing to do */
2451}
2452PRE_SYSCALL(uuidgen)(void *store_, long long count_) { /* Nothing to do */ }
2453POST_SYSCALL(uuidgen)(long long res, void *store_, long long count_) {
2454 /* Nothing to do */
2455}
2456PRE_SYSCALL(compat_90_getvfsstat)
2457(void *buf_, long long bufsize_, long long flags_) {
2458 /* Nothing to do */
2459}
2460POST_SYSCALL(compat_90_getvfsstat)
2461(long long res, void *buf_, long long bufsize_, long long flags_) {
2462 /* Nothing to do */
2463}
2464PRE_SYSCALL(compat_90_statvfs1)(void *path_, void *buf_, long long flags_) {
2465 const char *path = (const char *)path_;
2466 if (path) {
2467 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
2468 }
2469}
2470POST_SYSCALL(compat_90_statvfs1)
2471(long long res, void *path_, void *buf_, long long flags_) {
2472 const char *path = (const char *)path_;
2473 if (path) {
2474 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
2475 }
2476}
2477PRE_SYSCALL(compat_90_fstatvfs1)(long long fd_, void *buf_, long long flags_) {
2478 /* Nothing to do */
2479}
2480POST_SYSCALL(compat_90_fstatvfs1)
2481(long long res, long long fd_, void *buf_, long long flags_) {
2482 /* Nothing to do */
2483}
2484PRE_SYSCALL(compat_30_fhstatvfs1)(void *fhp_, void *buf_, long long flags_) {
2485 /* TODO */
2486}
2487POST_SYSCALL(compat_30_fhstatvfs1)
2488(long long res, void *fhp_, void *buf_, long long flags_) {
2489 /* TODO */
2490}
2491PRE_SYSCALL(extattrctl)
2492(void *path_, long long cmd_, void *filename_, long long attrnamespace_,
2493 void *attrname_) {
2494 const char *path = (const char *)path_;
2495 if (path) {
2496 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
2497 }
2498}
2499POST_SYSCALL(extattrctl)
2500(long long res, void *path_, long long cmd_, void *filename_,
2501 long long attrnamespace_, void *attrname_) {
2502 const char *path = (const char *)path_;
2503 if (path) {
2504 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
2505 }
2506}
2507PRE_SYSCALL(extattr_set_file)
2508(void *path_, long long attrnamespace_, void *attrname_, void *data_,
2509 long long nbytes_) {
2510 const char *path = (const char *)path_;
2511 if (path) {
2512 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
2513 }
2514}
2515POST_SYSCALL(extattr_set_file)
2516(long long res, void *path_, long long attrnamespace_, void *attrname_,
2517 void *data_, long long nbytes_) {
2518 const char *path = (const char *)path_;
2519 if (path) {
2520 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
2521 }
2522}
2523PRE_SYSCALL(extattr_get_file)
2524(void *path_, long long attrnamespace_, void *attrname_, void *data_,
2525 long long nbytes_) {
2526 const char *path = (const char *)path_;
2527 if (path) {
2528 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
2529 }
2530}
2531POST_SYSCALL(extattr_get_file)
2532(long long res, void *path_, long long attrnamespace_, void *attrname_,
2533 void *data_, long long nbytes_) {
2534 const char *path = (const char *)path_;
2535 if (path) {
2536 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
2537 }
2538}
2539PRE_SYSCALL(extattr_delete_file)
2540(void *path_, long long attrnamespace_, void *attrname_) {
2541 const char *path = (const char *)path_;
2542 if (path) {
2543 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
2544 }
2545}
2546POST_SYSCALL(extattr_delete_file)
2547(long long res, void *path_, long long attrnamespace_, void *attrname_) {
2548 const char *path = (const char *)path_;
2549 if (path) {
2550 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
2551 }
2552}
2553PRE_SYSCALL(extattr_set_fd)
2554(long long fd_, long long attrnamespace_, void *attrname_, void *data_,
2555 long long nbytes_) {
2556 /* TODO */
2557}
2558POST_SYSCALL(extattr_set_fd)
2559(long long res, long long fd_, long long attrnamespace_, void *attrname_,
2560 void *data_, long long nbytes_) {
2561 /* TODO */
2562}
2563PRE_SYSCALL(extattr_get_fd)
2564(long long fd_, long long attrnamespace_, void *attrname_, void *data_,
2565 long long nbytes_) {
2566 /* TODO */
2567}
2568POST_SYSCALL(extattr_get_fd)
2569(long long res, long long fd_, long long attrnamespace_, void *attrname_,
2570 void *data_, long long nbytes_) {
2571 /* TODO */
2572}
2573PRE_SYSCALL(extattr_delete_fd)
2574(long long fd_, long long attrnamespace_, void *attrname_) {
2575 /* TODO */
2576}
2577POST_SYSCALL(extattr_delete_fd)
2578(long long res, long long fd_, long long attrnamespace_, void *attrname_) {
2579 /* TODO */
2580}
2581PRE_SYSCALL(extattr_set_link)
2582(void *path_, long long attrnamespace_, void *attrname_, void *data_,
2583 long long nbytes_) {
2584 const char *path = (const char *)path_;
2585 if (path) {
2586 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
2587 }
2588}
2589POST_SYSCALL(extattr_set_link)
2590(long long res, void *path_, long long attrnamespace_, void *attrname_,
2591 void *data_, long long nbytes_) {
2592 const char *path = (const char *)path_;
2593 if (path) {
2594 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
2595 }
2596}
2597PRE_SYSCALL(extattr_get_link)
2598(void *path_, long long attrnamespace_, void *attrname_, void *data_,
2599 long long nbytes_) {
2600 const char *path = (const char *)path_;
2601 if (path) {
2602 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
2603 }
2604}
2605POST_SYSCALL(extattr_get_link)
2606(long long res, void *path_, long long attrnamespace_, void *attrname_,
2607 void *data_, long long nbytes_) {
2608 const char *path = (const char *)path_;
2609 if (path) {
2610 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
2611 }
2612}
2613PRE_SYSCALL(extattr_delete_link)
2614(void *path_, long long attrnamespace_, void *attrname_) {
2615 const char *path = (const char *)path_;
2616 if (path) {
2617 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
2618 }
2619}
2620POST_SYSCALL(extattr_delete_link)
2621(long long res, void *path_, long long attrnamespace_, void *attrname_) {
2622 const char *path = (const char *)path_;
2623 if (path) {
2624 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
2625 }
2626}
2627PRE_SYSCALL(extattr_list_fd)
2628(long long fd_, long long attrnamespace_, void *data_, long long nbytes_) {
2629 /* TODO */
2630}
2631POST_SYSCALL(extattr_list_fd)
2632(long long res, long long fd_, long long attrnamespace_, void *data_,
2633 long long nbytes_) {
2634 /* TODO */
2635}
2636PRE_SYSCALL(extattr_list_file)
2637(void *path_, long long attrnamespace_, void *data_, long long nbytes_) {
2638 const char *path = (const char *)path_;
2639 if (path) {
2640 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
2641 }
2642}
2643POST_SYSCALL(extattr_list_file)
2644(long long res, void *path_, long long attrnamespace_, void *data_,
2645 long long nbytes_) {
2646 const char *path = (const char *)path_;
2647 if (path) {
2648 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
2649 }
2650}
2651PRE_SYSCALL(extattr_list_link)
2652(void *path_, long long attrnamespace_, void *data_, long long nbytes_) {
2653 const char *path = (const char *)path_;
2654 if (path) {
2655 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
2656 }
2657}
2658POST_SYSCALL(extattr_list_link)
2659(long long res, void *path_, long long attrnamespace_, void *data_,
2660 long long nbytes_) {
2661 const char *path = (const char *)path_;
2662 if (path) {
2663 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
2664 }
2665}
2666PRE_SYSCALL(compat_50_pselect)
2667(long long nd_, void *in_, void *ou_, void *ex_, void *ts_, void *mask_) {
2668 /* TODO */
2669}
2670POST_SYSCALL(compat_50_pselect)
2671(long long res, long long nd_, void *in_, void *ou_, void *ex_, void *ts_,
2672 void *mask_) {
2673 /* TODO */
2674}
2675PRE_SYSCALL(compat_50_pollts)
2676(void *fds_, long long nfds_, void *ts_, void *mask_) {
2677 /* TODO */
2678}
2679POST_SYSCALL(compat_50_pollts)
2680(long long res, void *fds_, long long nfds_, void *ts_, void *mask_) {
2681 /* TODO */
2682}
2683PRE_SYSCALL(setxattr)
2684(void *path_, void *name_, void *value_, long long size_, long long flags_) {
2685 const char *path = (const char *)path_;
2686 if (path) {
2687 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
2688 }
2689}
2690POST_SYSCALL(setxattr)
2691(long long res, void *path_, void *name_, void *value_, long long size_,
2692 long long flags_) {
2693 const char *path = (const char *)path_;
2694 if (path) {
2695 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
2696 }
2697}
2698PRE_SYSCALL(lsetxattr)
2699(void *path_, void *name_, void *value_, long long size_, long long flags_) {
2700 const char *path = (const char *)path_;
2701 if (path) {
2702 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
2703 }
2704}
2705POST_SYSCALL(lsetxattr)
2706(long long res, void *path_, void *name_, void *value_, long long size_,
2707 long long flags_) {
2708 const char *path = (const char *)path_;
2709 if (path) {
2710 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
2711 }
2712}
2713PRE_SYSCALL(fsetxattr)
2714(long long fd_, void *name_, void *value_, long long size_, long long flags_) {
2715 /* Nothing to do */
2716}
2717POST_SYSCALL(fsetxattr)
2718(long long res, long long fd_, void *name_, void *value_, long long size_,
2719 long long flags_) {
2720 /* Nothing to do */
2721}
2722PRE_SYSCALL(getxattr)(void *path_, void *name_, void *value_, long long size_) {
2723 const char *path = (const char *)path_;
2724 if (path) {
2725 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
2726 }
2727}
2728POST_SYSCALL(getxattr)
2729(long long res, void *path_, void *name_, void *value_, long long size_) {
2730 const char *path = (const char *)path_;
2731 if (path) {
2732 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
2733 }
2734}
2735PRE_SYSCALL(lgetxattr)
2736(void *path_, void *name_, void *value_, long long size_) {
2737 const char *path = (const char *)path_;
2738 if (path) {
2739 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
2740 }
2741}
2742POST_SYSCALL(lgetxattr)
2743(long long res, void *path_, void *name_, void *value_, long long size_) {
2744 const char *path = (const char *)path_;
2745 if (path) {
2746 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
2747 }
2748}
2749PRE_SYSCALL(fgetxattr)
2750(long long fd_, void *name_, void *value_, long long size_) {
2751 /* Nothing to do */
2752}
2753POST_SYSCALL(fgetxattr)
2754(long long res, long long fd_, void *name_, void *value_, long long size_) {
2755 /* Nothing to do */
2756}
2757PRE_SYSCALL(listxattr)(void *path_, void *list_, long long size_) {
2758 const char *path = (const char *)path_;
2759 if (path) {
2760 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
2761 }
2762}
2763POST_SYSCALL(listxattr)
2764(long long res, void *path_, void *list_, long long size_) {
2765 const char *path = (const char *)path_;
2766 if (path) {
2767 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
2768 }
2769}
2770PRE_SYSCALL(llistxattr)(void *path_, void *list_, long long size_) {
2771 const char *path = (const char *)path_;
2772 if (path) {
2773 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
2774 }
2775}
2776POST_SYSCALL(llistxattr)
2777(long long res, void *path_, void *list_, long long size_) {
2778 const char *path = (const char *)path_;
2779 if (path) {
2780 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
2781 }
2782}
2783PRE_SYSCALL(flistxattr)(long long fd_, void *list_, long long size_) {
2784 /* TODO */
2785}
2786POST_SYSCALL(flistxattr)
2787(long long res, long long fd_, void *list_, long long size_) {
2788 /* TODO */
2789}
2790PRE_SYSCALL(removexattr)(void *path_, void *name_) {
2791 const char *path = (const char *)path_;
2792 if (path) {
2793 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
2794 }
2795}
2796POST_SYSCALL(removexattr)(long long res, void *path_, void *name_) {
2797 const char *path = (const char *)path_;
2798 if (path) {
2799 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
2800 }
2801}
2802PRE_SYSCALL(lremovexattr)(void *path_, void *name_) {
2803 const char *path = (const char *)path_;
2804 if (path) {
2805 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
2806 }
2807}
2808POST_SYSCALL(lremovexattr)(long long res, void *path_, void *name_) {
2809 const char *path = (const char *)path_;
2810 if (path) {
2811 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
2812 }
2813}
2814PRE_SYSCALL(fremovexattr)(long long fd_, void *name_) { /* TODO */ }
2815POST_SYSCALL(fremovexattr)(long long res, long long fd_, void *name_) {
2816 /* TODO */
2817}
2818PRE_SYSCALL(compat_50___stat30)(void *path_, void *ub_) { /* TODO */ }
2819POST_SYSCALL(compat_50___stat30)(long long res, void *path_, void *ub_) {
2820 /* TODO */
2821}
2822PRE_SYSCALL(compat_50___fstat30)(long long fd_, void *sb_) { /* TODO */ }
2823POST_SYSCALL(compat_50___fstat30)(long long res, long long fd_, void *sb_) {
2824 /* TODO */
2825}
2826PRE_SYSCALL(compat_50___lstat30)(void *path_, void *ub_) { /* TODO */ }
2827POST_SYSCALL(compat_50___lstat30)(long long res, void *path_, void *ub_) {
2828 /* TODO */
2829}
2830PRE_SYSCALL(__getdents30)(long long fd_, void *buf_, long long count_) {
2831 /* Nothing to do */
2832}
2833POST_SYSCALL(__getdents30)
2834(long long res, long long fd_, void *buf_, long long count_) {
2835 /* Nothing to do */
2836}
2837PRE_SYSCALL(posix_fadvise)(long long) { /* Nothing to do */ }
2838POST_SYSCALL(posix_fadvise)(long long res, long long) { /* Nothing to do */ }
2839PRE_SYSCALL(compat_30___fhstat30)(void *fhp_, void *sb_) { /* TODO */ }
2840POST_SYSCALL(compat_30___fhstat30)(long long res, void *fhp_, void *sb_) {
2841 /* TODO */
2842}
2843PRE_SYSCALL(compat_50___ntp_gettime30)(void *ntvp_) { /* TODO */ }
2844POST_SYSCALL(compat_50___ntp_gettime30)(long long res, void *ntvp_) {
2845 /* TODO */
2846}
2847PRE_SYSCALL(__socket30)
2848(long long domain_, long long type_, long long protocol_) {
2849 /* Nothing to do */
2850}
2851POST_SYSCALL(__socket30)
2852(long long res, long long domain_, long long type_, long long protocol_) {
2853 /* Nothing to do */
2854}
2855PRE_SYSCALL(__getfh30)(void *fname_, void *fhp_, void *fh_size_) {
2856 const char *fname = (const char *)fname_;
2857 if (fname) {
2858 PRE_READ(fname, __sanitizer::internal_strlen(fname) + 1);
2859 }
2860}
2861POST_SYSCALL(__getfh30)
2862(long long res, void *fname_, void *fhp_, void *fh_size_) {
2863 const char *fname = (const char *)fname_;
2864 if (res == 0) {
2865 if (fname) {
2866 POST_READ(fname, __sanitizer::internal_strlen(fname) + 1);
2867 }
2868 }
2869}
2870PRE_SYSCALL(__fhopen40)(void *fhp_, long long fh_size_, long long flags_) {
2871 if (fhp_) {
2872 PRE_READ(fhp_, fh_size_);
2873 }
2874}
2875POST_SYSCALL(__fhopen40)
2876(long long res, void *fhp_, long long fh_size_, long long flags_) {}
2877PRE_SYSCALL(compat_90_fhstatvfs1)
2878(void *fhp_, long long fh_size_, void *buf_, long long flags_) {
2879 if (fhp_) {
2880 PRE_READ(fhp_, fh_size_);
2881 }
2882}
2883POST_SYSCALL(compat_90_fhstatvfs1)
2884(long long res, void *fhp_, long long fh_size_, void *buf_, long long flags_) {}
2885PRE_SYSCALL(compat_50___fhstat40)(void *fhp_, long long fh_size_, void *sb_) {
2886 if (fhp_) {
2887 PRE_READ(fhp_, fh_size_);
2888 }
2889}
2890POST_SYSCALL(compat_50___fhstat40)
2891(long long res, void *fhp_, long long fh_size_, void *sb_) {}
2892PRE_SYSCALL(aio_cancel)(long long fildes_, void *aiocbp_) {
2893 if (aiocbp_) {
2894 PRE_READ(aiocbp_, sizeof(struct __sanitizer_aiocb));
2895 }
2896}
2897POST_SYSCALL(aio_cancel)(long long res, long long fildes_, void *aiocbp_) {}
2898PRE_SYSCALL(aio_error)(void *aiocbp_) {
2899 if (aiocbp_) {
2900 PRE_READ(aiocbp_, sizeof(struct __sanitizer_aiocb));
2901 }
2902}
2903POST_SYSCALL(aio_error)(long long res, void *aiocbp_) {}
2904PRE_SYSCALL(aio_fsync)(long long op_, void *aiocbp_) {
2905 if (aiocbp_) {
2906 PRE_READ(aiocbp_, sizeof(struct __sanitizer_aiocb));
2907 }
2908}
2909POST_SYSCALL(aio_fsync)(long long res, long long op_, void *aiocbp_) {}
2910PRE_SYSCALL(aio_read)(void *aiocbp_) {
2911 if (aiocbp_) {
2912 PRE_READ(aiocbp_, sizeof(struct __sanitizer_aiocb));
2913 }
2914}
2915POST_SYSCALL(aio_read)(long long res, void *aiocbp_) {}
2916PRE_SYSCALL(aio_return)(void *aiocbp_) {
2917 if (aiocbp_) {
2918 PRE_READ(aiocbp_, sizeof(struct __sanitizer_aiocb));
2919 }
2920}
2921POST_SYSCALL(aio_return)(long long res, void *aiocbp_) {}
2922PRE_SYSCALL(compat_50_aio_suspend)
2923(void *list_, long long nent_, void *timeout_) {
2924 /* TODO */
2925}
2926POST_SYSCALL(compat_50_aio_suspend)
2927(long long res, void *list_, long long nent_, void *timeout_) {
2928 /* TODO */
2929}
2930PRE_SYSCALL(aio_write)(void *aiocbp_) {
2931 if (aiocbp_) {
2932 PRE_READ(aiocbp_, sizeof(struct __sanitizer_aiocb));
2933 }
2934}
2935POST_SYSCALL(aio_write)(long long res, void *aiocbp_) {}
2936PRE_SYSCALL(lio_listio)
2937(long long mode_, void *list_, long long nent_, void *sig_) {
2938 /* Nothing to do */
2939}
2940POST_SYSCALL(lio_listio)
2941(long long res, long long mode_, void *list_, long long nent_, void *sig_) {
2942 /* Nothing to do */
2943}
2944/* syscall 407 has been skipped */
2945/* syscall 408 has been skipped */
2946/* syscall 409 has been skipped */
2947PRE_SYSCALL(__mount50)
2948(void *type_, void *path_, long long flags_, void *data_, long long data_len_) {
2949 const char *type = (const char *)type_;
2950 const char *path = (const char *)path_;
2951 if (type) {
2952 PRE_READ(type, __sanitizer::internal_strlen(type) + 1);
2953 }
2954 if (path) {
2955 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
2956 }
2957 if (data_) {
2958 PRE_READ(data_, data_len_);
2959 }
2960}
2961POST_SYSCALL(__mount50)
2962(long long res, void *type_, void *path_, long long flags_, void *data_,
2963 long long data_len_) {
2964 const char *type = (const char *)type_;
2965 const char *path = (const char *)path_;
2966 if (type) {
2967 POST_READ(type, __sanitizer::internal_strlen(type) + 1);
2968 }
2969 if (path) {
2970 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
2971 }
2972 if (data_) {
2973 POST_READ(data_, data_len_);
2974 }
2975}
2976PRE_SYSCALL(mremap)
2977(void *old_address_, long long old_size_, void *new_address_,
2978 long long new_size_, long long flags_) {
2979 /* Nothing to do */
2980}
2981POST_SYSCALL(mremap)
2982(long long res, void *old_address_, long long old_size_, void *new_address_,
2983 long long new_size_, long long flags_) {
2984 /* Nothing to do */
2985}
2986PRE_SYSCALL(pset_create)(void *psid_) { /* Nothing to do */ }
2987POST_SYSCALL(pset_create)(long long res, void *psid_) { /* Nothing to do */ }
2988PRE_SYSCALL(pset_destroy)(long long psid_) { /* Nothing to do */ }
2989POST_SYSCALL(pset_destroy)(long long res, long long psid_) {
2990 /* Nothing to do */
2991}
2992PRE_SYSCALL(pset_assign)(long long psid_, long long cpuid_, void *opsid_) {
2993 /* Nothing to do */
2994}
2995POST_SYSCALL(pset_assign)
2996(long long res, long long psid_, long long cpuid_, void *opsid_) {
2997 /* Nothing to do */
2998}
2999PRE_SYSCALL(_pset_bind)
3000(long long idtype_, long long first_id_, long long second_id_, long long psid_,
3001 void *opsid_) {
3002 /* Nothing to do */
3003}
3004POST_SYSCALL(_pset_bind)
3005(long long res, long long idtype_, long long first_id_, long long second_id_,
3006 long long psid_, void *opsid_) {
3007 /* Nothing to do */
3008}
3009PRE_SYSCALL(__posix_fadvise50)
3010(long long fd_, long long PAD_, long long offset_, long long len_,
3011 long long advice_) {
3012 /* Nothing to do */
3013}
3014POST_SYSCALL(__posix_fadvise50)
3015(long long res, long long fd_, long long PAD_, long long offset_,
3016 long long len_, long long advice_) {
3017 /* Nothing to do */
3018}
3019PRE_SYSCALL(__select50)
3020(long long nd_, void *in_, void *ou_, void *ex_, void *tv_) {
3021 /* Nothing to do */
3022}
3023POST_SYSCALL(__select50)
3024(long long res, long long nd_, void *in_, void *ou_, void *ex_, void *tv_) {
3025 /* Nothing to do */
3026}
3027PRE_SYSCALL(__gettimeofday50)(void *tp_, void *tzp_) { /* Nothing to do */ }
3028POST_SYSCALL(__gettimeofday50)(long long res, void *tp_, void *tzp_) {
3029 /* Nothing to do */
3030}
3031PRE_SYSCALL(__settimeofday50)(void *tv_, void *tzp_) {
3032 if (tv_) {
3033 PRE_READ(tv_, timeval_sz);
3034 }
3035 if (tzp_) {
3036 PRE_READ(tzp_, struct_timezone_sz);
3037 }
3038}
3039POST_SYSCALL(__settimeofday50)(long long res, void *tv_, void *tzp_) {}
3040PRE_SYSCALL(__utimes50)(void *path_, void *tptr_) {
3041 struct __sanitizer_timespec **tptr = (struct __sanitizer_timespec **)tptr_;
3042 const char *path = (const char *)path_;
3043 if (path) {
3044 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
3045 }
3046 if (tptr) {
3047 PRE_READ(tptr[0], struct_timespec_sz);
3048 PRE_READ(tptr[1], struct_timespec_sz);
3049 }
3050}
3051POST_SYSCALL(__utimes50)(long long res, void *path_, void *tptr_) {}
3052PRE_SYSCALL(__adjtime50)(void *delta_, void *olddelta_) {
3053 if (delta_) {
3054 PRE_READ(delta_, timeval_sz);
3055 }
3056}
3057POST_SYSCALL(__adjtime50)(long long res, void *delta_, void *olddelta_) {}
3058PRE_SYSCALL(__lfs_segwait50)(void *fsidp_, void *tv_) { /* TODO */ }
3059POST_SYSCALL(__lfs_segwait50)(long long res, void *fsidp_, void *tv_) {
3060 /* TODO */
3061}
3062PRE_SYSCALL(__futimes50)(long long fd_, void *tptr_) {
3063 struct __sanitizer_timespec **tptr = (struct __sanitizer_timespec **)tptr_;
3064 if (tptr) {
3065 PRE_READ(tptr[0], struct_timespec_sz);
3066 PRE_READ(tptr[1], struct_timespec_sz);
3067 }
3068}
3069POST_SYSCALL(__futimes50)(long long res, long long fd_, void *tptr_) {}
3070PRE_SYSCALL(__lutimes50)(void *path_, void *tptr_) {
3071 struct __sanitizer_timespec **tptr = (struct __sanitizer_timespec **)tptr_;
3072 const char *path = (const char *)path_;
3073 if (path) {
3074 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
3075 }
3076 if (tptr) {
3077 PRE_READ(tptr[0], struct_timespec_sz);
3078 PRE_READ(tptr[1], struct_timespec_sz);
3079 }
3080}
3081POST_SYSCALL(__lutimes50)(long long res, void *path_, void *tptr_) {
3082 struct __sanitizer_timespec **tptr = (struct __sanitizer_timespec **)tptr_;
3083 const char *path = (const char *)path_;
3084 if (path) {
3085 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
3086 }
3087 if (tptr) {
3088 POST_READ(tptr[0], struct_timespec_sz);
3089 POST_READ(tptr[1], struct_timespec_sz);
3090 }
3091}
3092PRE_SYSCALL(__setitimer50)(long long which_, void *itv_, void *oitv_) {
3093 struct __sanitizer_itimerval *itv = (struct __sanitizer_itimerval *)itv_;
3094 if (itv) {
3095 PRE_READ(&itv->it_interval.tv_sec, sizeof(__sanitizer_time_t));
3096 PRE_READ(&itv->it_interval.tv_usec, sizeof(__sanitizer_suseconds_t));
3097 PRE_READ(&itv->it_value.tv_sec, sizeof(__sanitizer_time_t));
3098 PRE_READ(&itv->it_value.tv_usec, sizeof(__sanitizer_suseconds_t));
3099 }
3100}
3101POST_SYSCALL(__setitimer50)
3102(long long res, long long which_, void *itv_, void *oitv_) {}
3103PRE_SYSCALL(__getitimer50)(long long which_, void *itv_) { /* Nothing to do */ }
3104POST_SYSCALL(__getitimer50)(long long res, long long which_, void *itv_) {
3105 /* Nothing to do */
3106}
3107PRE_SYSCALL(__clock_gettime50)(long long clock_id_, void *tp_) {
3108 /* Nothing to do */
3109}
3110POST_SYSCALL(__clock_gettime50)(long long res, long long clock_id_, void *tp_) {
3111 /* Nothing to do */
3112}
3113PRE_SYSCALL(__clock_settime50)(long long clock_id_, void *tp_) {
3114 if (tp_) {
3115 PRE_READ(tp_, struct_timespec_sz);
3116 }
3117}
3118POST_SYSCALL(__clock_settime50)
3119(long long res, long long clock_id_, void *tp_) {}
3120PRE_SYSCALL(__clock_getres50)(long long clock_id_, void *tp_) {
3121 /* Nothing to do */
3122}
3123POST_SYSCALL(__clock_getres50)(long long res, long long clock_id_, void *tp_) {
3124 /* Nothing to do */
3125}
3126PRE_SYSCALL(__nanosleep50)(void *rqtp_, void *rmtp_) {
3127 if (rqtp_) {
3128 PRE_READ(rqtp_, struct_timespec_sz);
3129 }
3130}
3131POST_SYSCALL(__nanosleep50)(long long res, void *rqtp_, void *rmtp_) {}
3132PRE_SYSCALL(____sigtimedwait50)(void *set_, void *info_, void *timeout_) {
3133 if (set_) {
3134 PRE_READ(set_, sizeof(__sanitizer_sigset_t));
3135 }
3136 if (timeout_) {
3137 PRE_READ(timeout_, struct_timespec_sz);
3138 }
3139}
3140POST_SYSCALL(____sigtimedwait50)
3141(long long res, void *set_, void *info_, void *timeout_) {}
3142PRE_SYSCALL(__mq_timedsend50)
3143(long long mqdes_, void *msg_ptr_, long long msg_len_, long long msg_prio_,
3144 void *abs_timeout_) {
3145 if (msg_ptr_) {
3146 PRE_READ(msg_ptr_, msg_len_);
3147 }
3148 if (abs_timeout_) {
3149 PRE_READ(abs_timeout_, struct_timespec_sz);
3150 }
3151}
3152POST_SYSCALL(__mq_timedsend50)
3153(long long res, long long mqdes_, void *msg_ptr_, long long msg_len_,
3154 long long msg_prio_, void *abs_timeout_) {}
3155PRE_SYSCALL(__mq_timedreceive50)
3156(long long mqdes_, void *msg_ptr_, long long msg_len_, void *msg_prio_,
3157 void *abs_timeout_) {
3158 if (msg_ptr_) {
3159 PRE_READ(msg_ptr_, msg_len_);
3160 }
3161 if (abs_timeout_) {
3162 PRE_READ(abs_timeout_, struct_timespec_sz);
3163 }
3164}
3165POST_SYSCALL(__mq_timedreceive50)
3166(long long res, long long mqdes_, void *msg_ptr_, long long msg_len_,
3167 void *msg_prio_, void *abs_timeout_) {}
3168PRE_SYSCALL(compat_60__lwp_park)
3169(void *ts_, long long unpark_, void *hint_, void *unparkhint_) {
3170 /* TODO */
3171}
3172POST_SYSCALL(compat_60__lwp_park)
3173(long long res, void *ts_, long long unpark_, void *hint_, void *unparkhint_) {
3174 /* TODO */
3175}
3176PRE_SYSCALL(__kevent50)
3177(long long fd_, void *changelist_, long long nchanges_, void *eventlist_,
3178 long long nevents_, void *timeout_) {
3179 if (changelist_) {
3180 PRE_READ(changelist_, nchanges_ * struct_kevent_sz);
3181 }
3182 if (timeout_) {
3183 PRE_READ(timeout_, struct_timespec_sz);
3184 }
3185}
3186POST_SYSCALL(__kevent50)
3187(long long res, long long fd_, void *changelist_, long long nchanges_,
3188 void *eventlist_, long long nevents_, void *timeout_) {}
3189PRE_SYSCALL(__pselect50)
3190(long long nd_, void *in_, void *ou_, void *ex_, void *ts_, void *mask_) {
3191 if (ts_) {
3192 PRE_READ(ts_, struct_timespec_sz);
3193 }
3194 if (mask_) {
3195 PRE_READ(mask_, sizeof(struct __sanitizer_sigset_t));
3196 }
3197}
3198POST_SYSCALL(__pselect50)
3199(long long res, long long nd_, void *in_, void *ou_, void *ex_, void *ts_,
3200 void *mask_) {}
3201PRE_SYSCALL(__pollts50)(void *fds_, long long nfds_, void *ts_, void *mask_) {
3202 if (ts_) {
3203 PRE_READ(ts_, struct_timespec_sz);
3204 }
3205 if (mask_) {
3206 PRE_READ(mask_, sizeof(struct __sanitizer_sigset_t));
3207 }
3208}
3209POST_SYSCALL(__pollts50)
3210(long long res, void *fds_, long long nfds_, void *ts_, void *mask_) {}
3211PRE_SYSCALL(__aio_suspend50)(void *list_, long long nent_, void *timeout_) {
3212 int i;
3213 const struct aiocb *const *list = (const struct aiocb *const *)list_;
3214 if (list) {
3215 for (i = 0; i < nent_; i++) {
3216 if (list[i]) {
3217 PRE_READ(list[i], sizeof(struct __sanitizer_aiocb));
3218 }
3219 }
3220 }
3221 if (timeout_) {
3222 PRE_READ(timeout_, struct_timespec_sz);
3223 }
3224}
3225POST_SYSCALL(__aio_suspend50)
3226(long long res, void *list_, long long nent_, void *timeout_) {}
3227PRE_SYSCALL(__stat50)(void *path_, void *ub_) {
3228 const char *path = (const char *)path_;
3229 if (path) {
3230 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
3231 }
3232}
3233POST_SYSCALL(__stat50)(long long res, void *path_, void *ub_) {
3234 const char *path = (const char *)path_;
3235 if (res == 0) {
3236 if (path) {
3237 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
3238 }
3239 }
3240}
3241PRE_SYSCALL(__fstat50)(long long fd_, void *sb_) { /* Nothing to do */ }
3242POST_SYSCALL(__fstat50)(long long res, long long fd_, void *sb_) {
3243 /* Nothing to do */
3244}
3245PRE_SYSCALL(__lstat50)(void *path_, void *ub_) {
3246 const char *path = (const char *)path_;
3247 if (path) {
3248 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
3249 }
3250}
3251POST_SYSCALL(__lstat50)(long long res, void *path_, void *ub_) {
3252 const char *path = (const char *)path_;
3253 if (res == 0) {
3254 if (path) {
3255 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
3256 }
3257 }
3258}
3259PRE_SYSCALL(____semctl50)
3260(long long semid_, long long semnum_, long long cmd_, void *arg_) {
3261 /* Nothing to do */
3262}
3263POST_SYSCALL(____semctl50)
3264(long long res, long long semid_, long long semnum_, long long cmd_,
3265 void *arg_) {
3266 /* Nothing to do */
3267}
3268PRE_SYSCALL(__shmctl50)(long long shmid_, long long cmd_, void *buf_) {
3269 /* Nothing to do */
3270}
3271POST_SYSCALL(__shmctl50)
3272(long long res, long long shmid_, long long cmd_, void *buf_) {
3273 /* Nothing to do */
3274}
3275PRE_SYSCALL(__msgctl50)(long long msqid_, long long cmd_, void *buf_) {
3276 /* Nothing to do */
3277}
3278POST_SYSCALL(__msgctl50)
3279(long long res, long long msqid_, long long cmd_, void *buf_) {
3280 /* Nothing to do */
3281}
3282PRE_SYSCALL(__getrusage50)(long long who_, void *rusage_) {
3283 /* Nothing to do */
3284}
3285POST_SYSCALL(__getrusage50)(long long res, long long who_, void *rusage_) {
3286 /* Nothing to do */
3287}
3288PRE_SYSCALL(__timer_settime50)
3289(long long timerid_, long long flags_, void *value_, void *ovalue_) {
3290 struct __sanitizer_itimerval *value = (struct __sanitizer_itimerval *)value_;
3291 if (value) {
3292 PRE_READ(&value->it_interval.tv_sec, sizeof(__sanitizer_time_t));
3293 PRE_READ(&value->it_interval.tv_usec, sizeof(__sanitizer_suseconds_t));
3294 PRE_READ(&value->it_value.tv_sec, sizeof(__sanitizer_time_t));
3295 PRE_READ(&value->it_value.tv_usec, sizeof(__sanitizer_suseconds_t));
3296 }
3297}
3298POST_SYSCALL(__timer_settime50)
3299(long long res, long long timerid_, long long flags_, void *value_,
3300 void *ovalue_) {
3301 struct __sanitizer_itimerval *value = (struct __sanitizer_itimerval *)value_;
3302 if (res == 0) {
3303 if (value) {
3304 POST_READ(&value->it_interval.tv_sec, sizeof(__sanitizer_time_t));
3305 POST_READ(&value->it_interval.tv_usec, sizeof(__sanitizer_suseconds_t));
3306 POST_READ(&value->it_value.tv_sec, sizeof(__sanitizer_time_t));
3307 POST_READ(&value->it_value.tv_usec, sizeof(__sanitizer_suseconds_t));
3308 }
3309 }
3310}
3311PRE_SYSCALL(__timer_gettime50)(long long timerid_, void *value_) {
3312 /* Nothing to do */
3313}
3314POST_SYSCALL(__timer_gettime50)
3315(long long res, long long timerid_, void *value_) {
3316 /* Nothing to do */
3317}
3318#if defined(NTP) || !defined(_KERNEL_OPT)
3319PRE_SYSCALL(__ntp_gettime50)(void *ntvp_) { /* Nothing to do */ }
3320POST_SYSCALL(__ntp_gettime50)(long long res, void *ntvp_) {
3321 /* Nothing to do */
3322}
3323#else
3324/* syscall 448 has been skipped */
3325#endif
3326PRE_SYSCALL(__wait450)
3327(long long pid_, void *status_, long long options_, void *rusage_) {
3328 /* Nothing to do */
3329}
3330POST_SYSCALL(__wait450)
3331(long long res, long long pid_, void *status_, long long options_,
3332 void *rusage_) {
3333 /* Nothing to do */
3334}
3335PRE_SYSCALL(__mknod50)(void *path_, long long mode_, long long dev_) {
3336 const char *path = (const char *)path_;
3337 if (path) {
3338 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
3339 }
3340}
3341POST_SYSCALL(__mknod50)
3342(long long res, void *path_, long long mode_, long long dev_) {
3343 const char *path = (const char *)path_;
3344 if (res == 0) {
3345 if (path) {
3346 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
3347 }
3348 }
3349}
3350PRE_SYSCALL(__fhstat50)(void *fhp_, long long fh_size_, void *sb_) {
3351 if (fhp_) {
3352 PRE_READ(fhp_, fh_size_);
3353 }
3354}
3355POST_SYSCALL(__fhstat50)
3356(long long res, void *fhp_, long long fh_size_, void *sb_) {
3357 if (res == 0) {
3358 if (fhp_) {
3359 POST_READ(fhp_, fh_size_);
3360 }
3361 }
3362}
3363/* syscall 452 has been skipped */
3364PRE_SYSCALL(pipe2)(void *fildes_, long long flags_) { /* Nothing to do */ }
3365POST_SYSCALL(pipe2)(long long res, void *fildes_, long long flags_) {
3366 /* Nothing to do */
3367}
3368PRE_SYSCALL(dup3)(long long from_, long long to_, long long flags_) {
3369 /* Nothing to do */
3370}
3371POST_SYSCALL(dup3)
3372(long long res, long long from_, long long to_, long long flags_) {
3373 /* Nothing to do */
3374}
3375PRE_SYSCALL(kqueue1)(long long flags_) { /* Nothing to do */ }
3376POST_SYSCALL(kqueue1)(long long res, long long flags_) { /* Nothing to do */ }
3377PRE_SYSCALL(paccept)
3378(long long s_, void *name_, void *anamelen_, void *mask_, long long flags_) {
3379 if (mask_) {
3380 PRE_READ(mask_, sizeof(__sanitizer_sigset_t));
3381 }
3382}
3383POST_SYSCALL(paccept)
3384(long long res, long long s_, void *name_, void *anamelen_, void *mask_,
3385 long long flags_) {
3386 if (res >= 0) {
3387 if (mask_) {
3388 PRE_READ(mask_, sizeof(__sanitizer_sigset_t));
3389 }
3390 }
3391}
3392PRE_SYSCALL(linkat)
3393(long long fd1_, void *name1_, long long fd2_, void *name2_, long long flags_) {
3394 const char *name1 = (const char *)name1_;
3395 const char *name2 = (const char *)name2_;
3396 if (name1) {
3397 PRE_READ(name1, __sanitizer::internal_strlen(name1) + 1);
3398 }
3399 if (name2) {
3400 PRE_READ(name2, __sanitizer::internal_strlen(name2) + 1);
3401 }
3402}
3403POST_SYSCALL(linkat)
3404(long long res, long long fd1_, void *name1_, long long fd2_, void *name2_,
3405 long long flags_) {
3406 const char *name1 = (const char *)name1_;
3407 const char *name2 = (const char *)name2_;
3408 if (res == 0) {
3409 if (name1) {
3410 POST_READ(name1, __sanitizer::internal_strlen(name1) + 1);
3411 }
3412 if (name2) {
3413 POST_READ(name2, __sanitizer::internal_strlen(name2) + 1);
3414 }
3415 }
3416}
3417PRE_SYSCALL(renameat)
3418(long long fromfd_, void *from_, long long tofd_, void *to_) {
3419 const char *from = (const char *)from_;
3420 const char *to = (const char *)to_;
3421 if (from) {
3422 PRE_READ(from, __sanitizer::internal_strlen(from) + 1);
3423 }
3424 if (to) {
3425 PRE_READ(to, __sanitizer::internal_strlen(to) + 1);
3426 }
3427}
3428POST_SYSCALL(renameat)
3429(long long res, long long fromfd_, void *from_, long long tofd_, void *to_) {
3430 const char *from = (const char *)from_;
3431 const char *to = (const char *)to_;
3432 if (res == 0) {
3433 if (from) {
3434 POST_READ(from, __sanitizer::internal_strlen(from) + 1);
3435 }
3436 if (to) {
3437 POST_READ(to, __sanitizer::internal_strlen(to) + 1);
3438 }
3439 }
3440}
3441PRE_SYSCALL(mkfifoat)(long long fd_, void *path_, long long mode_) {
3442 const char *path = (const char *)path_;
3443 if (path) {
3444 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
3445 }
3446}
3447POST_SYSCALL(mkfifoat)
3448(long long res, long long fd_, void *path_, long long mode_) {
3449 const char *path = (const char *)path_;
3450 if (res == 0) {
3451 if (path) {
3452 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
3453 }
3454 }
3455}
3456PRE_SYSCALL(mknodat)
3457(long long fd_, void *path_, long long mode_, long long PAD_, long long dev_) {
3458 const char *path = (const char *)path_;
3459 if (path) {
3460 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
3461 }
3462}
3463POST_SYSCALL(mknodat)
3464(long long res, long long fd_, void *path_, long long mode_, long long PAD_,
3465 long long dev_) {
3466 const char *path = (const char *)path_;
3467 if (res == 0) {
3468 if (path) {
3469 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
3470 }
3471 }
3472}
3473PRE_SYSCALL(mkdirat)(long long fd_, void *path_, long long mode_) {
3474 const char *path = (const char *)path_;
3475 if (path) {
3476 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
3477 }
3478}
3479POST_SYSCALL(mkdirat)
3480(long long res, long long fd_, void *path_, long long mode_) {
3481 const char *path = (const char *)path_;
3482 if (res == 0) {
3483 if (path) {
3484 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
3485 }
3486 }
3487}
3488PRE_SYSCALL(faccessat)
3489(long long fd_, void *path_, long long amode_, long long flag_) {
3490 const char *path = (const char *)path_;
3491 if (path) {
3492 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
3493 }
3494}
3495POST_SYSCALL(faccessat)
3496(long long res, long long fd_, void *path_, long long amode_, long long flag_) {
3497 const char *path = (const char *)path_;
3498 if (res == 0) {
3499 if (path) {
3500 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
3501 }
3502 }
3503}
3504PRE_SYSCALL(fchmodat)
3505(long long fd_, void *path_, long long mode_, long long flag_) {
3506 const char *path = (const char *)path_;
3507 if (path) {
3508 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
3509 }
3510}
3511POST_SYSCALL(fchmodat)
3512(long long res, long long fd_, void *path_, long long mode_, long long flag_) {
3513 const char *path = (const char *)path_;
3514 if (res == 0) {
3515 if (path) {
3516 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
3517 }
3518 }
3519}
3520PRE_SYSCALL(fchownat)
3521(long long fd_, void *path_, long long owner_, long long group_,
3522 long long flag_) {
3523 const char *path = (const char *)path_;
3524 if (path) {
3525 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
3526 }
3527}
3528POST_SYSCALL(fchownat)
3529(long long res, long long fd_, void *path_, long long owner_, long long group_,
3530 long long flag_) {
3531 const char *path = (const char *)path_;
3532 if (res == 0) {
3533 if (path) {
3534 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
3535 }
3536 }
3537}
3538PRE_SYSCALL(fexecve)(long long fd_, void *argp_, void *envp_) { /* TODO */ }
3539POST_SYSCALL(fexecve)(long long res, long long fd_, void *argp_, void *envp_) {
3540 /* TODO */
3541}
3542PRE_SYSCALL(fstatat)(long long fd_, void *path_, void *buf_, long long flag_) {
3543 const char *path = (const char *)path_;
3544 if (path) {
3545 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
3546 }
3547}
3548POST_SYSCALL(fstatat)
3549(long long res, long long fd_, void *path_, void *buf_, long long flag_) {
3550 const char *path = (const char *)path_;
3551 if (path) {
3552 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
3553 }
3554}
3555PRE_SYSCALL(utimensat)
3556(long long fd_, void *path_, void *tptr_, long long flag_) {
3557 const char *path = (const char *)path_;
3558 if (path) {
3559 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
3560 }
3561 if (tptr_) {
3562 PRE_READ(tptr_, struct_timespec_sz);
3563 }
3564}
3565POST_SYSCALL(utimensat)
3566(long long res, long long fd_, void *path_, void *tptr_, long long flag_) {
3567 const char *path = (const char *)path_;
3568 if (res > 0) {
3569 if (path) {
3570 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
3571 }
3572 if (tptr_) {
3573 POST_READ(tptr_, struct_timespec_sz);
3574 }
3575 }
3576}
3577PRE_SYSCALL(openat)
3578(long long fd_, void *path_, long long oflags_, long long mode_) {
3579 const char *path = (const char *)path_;
3580 if (path) {
3581 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
3582 }
3583}
3584POST_SYSCALL(openat)
3585(long long res, long long fd_, void *path_, long long oflags_,
3586 long long mode_) {
3587 const char *path = (const char *)path_;
3588 if (res > 0) {
3589 if (path) {
3590 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
3591 }
3592 }
3593}
3594PRE_SYSCALL(readlinkat)
3595(long long fd_, void *path_, void *buf_, long long bufsize_) {
3596 const char *path = (const char *)path_;
3597 if (path) {
3598 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
3599 }
3600}
3601POST_SYSCALL(readlinkat)
3602(long long res, long long fd_, void *path_, void *buf_, long long bufsize_) {
3603 const char *path = (const char *)path_;
3604 if (res > 0) {
3605 if (path) {
3606 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
3607 }
3608 }
3609}
3610PRE_SYSCALL(symlinkat)(void *path1_, long long fd_, void *path2_) {
3611 const char *path1 = (const char *)path1_;
3612 const char *path2 = (const char *)path2_;
3613 if (path1) {
3614 PRE_READ(path1, __sanitizer::internal_strlen(path1) + 1);
3615 }
3616 if (path2) {
3617 PRE_READ(path2, __sanitizer::internal_strlen(path2) + 1);
3618 }
3619}
3620POST_SYSCALL(symlinkat)
3621(long long res, void *path1_, long long fd_, void *path2_) {
3622 const char *path1 = (const char *)path1_;
3623 const char *path2 = (const char *)path2_;
3624 if (res == 0) {
3625 if (path1) {
3626 POST_READ(path1, __sanitizer::internal_strlen(path1) + 1);
3627 }
3628 if (path2) {
3629 POST_READ(path2, __sanitizer::internal_strlen(path2) + 1);
3630 }
3631 }
3632}
3633PRE_SYSCALL(unlinkat)(long long fd_, void *path_, long long flag_) {
3634 const char *path = (const char *)path_;
3635 if (path) {
3636 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
3637 }
3638}
3639POST_SYSCALL(unlinkat)
3640(long long res, long long fd_, void *path_, long long flag_) {
3641 const char *path = (const char *)path_;
3642 if (res == 0) {
3643 if (path) {
3644 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
3645 }
3646 }
3647}
3648PRE_SYSCALL(futimens)(long long fd_, void *tptr_) {
3649 struct __sanitizer_timespec **tptr = (struct __sanitizer_timespec **)tptr_;
3650 if (tptr) {
3651 PRE_READ(tptr[0], struct_timespec_sz);
3652 PRE_READ(tptr[1], struct_timespec_sz);
3653 }
3654}
3655POST_SYSCALL(futimens)(long long res, long long fd_, void *tptr_) {
3656 struct __sanitizer_timespec **tptr = (struct __sanitizer_timespec **)tptr_;
3657 if (res == 0) {
3658 if (tptr) {
3659 POST_READ(tptr[0], struct_timespec_sz);
3660 POST_READ(tptr[1], struct_timespec_sz);
3661 }
3662 }
3663}
3664PRE_SYSCALL(__quotactl)(void *path_, void *args_) {
3665 const char *path = (const char *)path_;
3666 if (path) {
3667 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
3668 }
3669}
3670POST_SYSCALL(__quotactl)(long long res, void *path_, void *args_) {
3671 const char *path = (const char *)path_;
3672 if (res == 0) {
3673 if (path) {
3674 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
3675 }
3676 }
3677}
3678PRE_SYSCALL(posix_spawn)
3679(void *pid_, void *path_, void *file_actions_, void *attrp_, void *argv_,
3680 void *envp_) {
3681 const char *path = (const char *)path_;
3682 if (path) {
3683 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
3684 }
3685}
3686POST_SYSCALL(posix_spawn)
3687(long long res, void *pid_, void *path_, void *file_actions_, void *attrp_,
3688 void *argv_, void *envp_) {
3689 const char *path = (const char *)path_;
3690 if (pid_) {
3691 if (path) {
3692 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
3693 }
3694 }
3695}
3696PRE_SYSCALL(recvmmsg)
3697(long long s_, void *mmsg_, long long vlen_, long long flags_, void *timeout_) {
3698 if (timeout_) {
3699 PRE_READ(timeout_, struct_timespec_sz);
3700 }
3701}
3702POST_SYSCALL(recvmmsg)
3703(long long res, long long s_, void *mmsg_, long long vlen_, long long flags_,
3704 void *timeout_) {
3705 if (res >= 0) {
3706 if (timeout_) {
3707 POST_READ(timeout_, struct_timespec_sz);
3708 }
3709 }
3710}
3711PRE_SYSCALL(sendmmsg)
3712(long long s_, void *mmsg_, long long vlen_, long long flags_) {
3713 struct __sanitizer_mmsghdr *mmsg = (struct __sanitizer_mmsghdr *)mmsg_;
3714 if (mmsg) {
3715 PRE_READ(mmsg, sizeof(struct __sanitizer_mmsghdr) *
3716 (vlen_ > 1024 ? 1024 : vlen_));
3717 }
3718}
3719POST_SYSCALL(sendmmsg)
3720(long long res, long long s_, void *mmsg_, long long vlen_, long long flags_) {
3721 struct __sanitizer_mmsghdr *mmsg = (struct __sanitizer_mmsghdr *)mmsg_;
3722 if (res >= 0) {
3723 if (mmsg) {
3724 POST_READ(mmsg, sizeof(struct __sanitizer_mmsghdr) *
3725 (vlen_ > 1024 ? 1024 : vlen_));
3726 }
3727 }
3728}
3729PRE_SYSCALL(clock_nanosleep)
3730(long long clock_id_, long long flags_, void *rqtp_, void *rmtp_) {
3731 if (rqtp_) {
3732 PRE_READ(rqtp_, struct_timespec_sz);
3733 }
3734}
3735POST_SYSCALL(clock_nanosleep)
3736(long long res, long long clock_id_, long long flags_, void *rqtp_,
3737 void *rmtp_) {
3738 if (rqtp_) {
3739 POST_READ(rqtp_, struct_timespec_sz);
3740 }
3741}
3742PRE_SYSCALL(___lwp_park60)
3743(long long clock_id_, long long flags_, void *ts_, long long unpark_,
3744 void *hint_, void *unparkhint_) {
3745 if (ts_) {
3746 PRE_READ(ts_, struct_timespec_sz);
3747 }
3748}
3749POST_SYSCALL(___lwp_park60)
3750(long long res, long long clock_id_, long long flags_, void *ts_,
3751 long long unpark_, void *hint_, void *unparkhint_) {
3752 if (res == 0) {
3753 if (ts_) {
3754 POST_READ(ts_, struct_timespec_sz);
3755 }
3756 }
3757}
3758PRE_SYSCALL(posix_fallocate)
3759(long long fd_, long long PAD_, long long pos_, long long len_) {
3760 /* Nothing to do */
3761}
3762POST_SYSCALL(posix_fallocate)
3763(long long res, long long fd_, long long PAD_, long long pos_, long long len_) {
3764 /* Nothing to do */
3765}
3766PRE_SYSCALL(fdiscard)
3767(long long fd_, long long PAD_, long long pos_, long long len_) {
3768 /* Nothing to do */
3769}
3770POST_SYSCALL(fdiscard)
3771(long long res, long long fd_, long long PAD_, long long pos_, long long len_) {
3772 /* Nothing to do */
3773}
3774PRE_SYSCALL(wait6)
3775(long long idtype_, long long id_, void *status_, long long options_,
3776 void *wru_, void *info_) {
3777 /* Nothing to do */
3778}
3779POST_SYSCALL(wait6)
3780(long long res, long long idtype_, long long id_, void *status_,
3781 long long options_, void *wru_, void *info_) {
3782 /* Nothing to do */
3783}
3784PRE_SYSCALL(clock_getcpuclockid2)
3785(long long idtype_, long long id_, void *clock_id_) {
3786 /* Nothing to do */
3787}
3788POST_SYSCALL(clock_getcpuclockid2)
3789(long long res, long long idtype_, long long id_, void *clock_id_) {
3790 /* Nothing to do */
3791}
3792PRE_SYSCALL(__getvfsstat90)(void *buf_, long long bufsize_, long long flags_) {
3793 /* Nothing to do */
3794}
3795POST_SYSCALL(__getvfsstat90)
3796(long long res, void *buf_, long long bufsize_, long long flags_) {
3797 /* Nothing to do */
3798}
3799PRE_SYSCALL(__statvfs190)(void *path_, void *buf_, long long flags_) {
3800 const char *path = (const char *)path_;
3801 if (path) {
3802 PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
3803 }
3804}
3805POST_SYSCALL(__statvfs190)
3806(long long res, void *path_, void *buf_, long long flags_) {
3807 const char *path = (const char *)path_;
3808 if (path) {
3809 POST_READ(path, __sanitizer::internal_strlen(path) + 1);
3810 }
3811}
3812PRE_SYSCALL(__fstatvfs190)(long long fd_, void *buf_, long long flags_) {
3813 /* Nothing to do */
3814}
3815POST_SYSCALL(__fstatvfs190)
3816(long long res, long long fd_, void *buf_, long long flags_) {
3817 /* Nothing to do */
3818}
3819PRE_SYSCALL(__fhstatvfs190)
3820(void *fhp_, long long fh_size_, void *buf_, long long flags_) {
3821 if (fhp_) {
3822 PRE_READ(fhp_, fh_size_);
3823 }
3824}
3825POST_SYSCALL(__fhstatvfs190)
3826(long long res, void *fhp_, long long fh_size_, void *buf_, long long flags_) {}
3827#undef SYS_MAXSYSARGS
3828} // extern "C"
3829
3830#undef PRE_SYSCALL
3831#undef PRE_READ
3832#undef PRE_WRITE
3833#undef POST_SYSCALL
3834#undef POST_READ
3835#undef POST_WRITE
3836
3837#endif // SANITIZER_NETBSD
lib/tsan/sanitizer_common/sanitizer_termination.cpp created+94
...@@ -0,0 +1,94 @@
1//===-- sanitizer_termination.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 contains the Sanitizer termination functions CheckFailed and Die,
10/// and the callback functionalities associated with them.
11///
12//===----------------------------------------------------------------------===//
13
14#include "sanitizer_common.h"
15#include "sanitizer_libc.h"
16
17namespace __sanitizer {
18
19static const int kMaxNumOfInternalDieCallbacks = 5;
20static DieCallbackType InternalDieCallbacks[kMaxNumOfInternalDieCallbacks];
21
22bool AddDieCallback(DieCallbackType callback) {
23 for (int i = 0; i < kMaxNumOfInternalDieCallbacks; i++) {
24 if (InternalDieCallbacks[i] == nullptr) {
25 InternalDieCallbacks[i] = callback;
26 return true;
27 }
28 }
29 return false;
30}
31
32bool RemoveDieCallback(DieCallbackType callback) {
33 for (int i = 0; i < kMaxNumOfInternalDieCallbacks; i++) {
34 if (InternalDieCallbacks[i] == callback) {
35 internal_memmove(&InternalDieCallbacks[i], &InternalDieCallbacks[i + 1],
36 sizeof(InternalDieCallbacks[0]) *
37 (kMaxNumOfInternalDieCallbacks - i - 1));
38 InternalDieCallbacks[kMaxNumOfInternalDieCallbacks - 1] = nullptr;
39 return true;
40 }
41 }
42 return false;
43}
44
45static DieCallbackType UserDieCallback;
46void SetUserDieCallback(DieCallbackType callback) {
47 UserDieCallback = callback;
48}
49
50void NORETURN Die() {
51 if (UserDieCallback)
52 UserDieCallback();
53 for (int i = kMaxNumOfInternalDieCallbacks - 1; i >= 0; i--) {
54 if (InternalDieCallbacks[i])
55 InternalDieCallbacks[i]();
56 }
57 if (common_flags()->abort_on_error)
58 Abort();
59 internal__exit(common_flags()->exitcode);
60}
61
62static CheckFailedCallbackType CheckFailedCallback;
63void SetCheckFailedCallback(CheckFailedCallbackType callback) {
64 CheckFailedCallback = callback;
65}
66
67const int kSecondsToSleepWhenRecursiveCheckFailed = 2;
68
69void NORETURN CheckFailed(const char *file, int line, const char *cond,
70 u64 v1, u64 v2) {
71 static atomic_uint32_t num_calls;
72 if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) > 10) {
73 SleepForSeconds(kSecondsToSleepWhenRecursiveCheckFailed);
74 Trap();
75 }
76
77 if (CheckFailedCallback) {
78 CheckFailedCallback(file, line, cond, v1, v2);
79 }
80 Report("Sanitizer CHECK failed: %s:%d %s (%lld, %lld)\n", file, line, cond,
81 v1, v2);
82 Die();
83}
84
85} // namespace __sanitizer
86
87using namespace __sanitizer;
88
89extern "C" {
90SANITIZER_INTERFACE_ATTRIBUTE
91void __sanitizer_set_death_callback(void (*callback)(void)) {
92 SetUserDieCallback(callback);
93}
94} // extern "C"
lib/tsan/sanitizer_common/sanitizer_thread_registry.cpp created+351
...@@ -0,0 +1,351 @@
1//===-- sanitizer_thread_registry.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 shared between sanitizer tools.
10//
11// General thread bookkeeping functionality.
12//===----------------------------------------------------------------------===//
13
14#include "sanitizer_thread_registry.h"
15
16namespace __sanitizer {
17
18ThreadContextBase::ThreadContextBase(u32 tid)
19 : tid(tid), unique_id(0), reuse_count(), os_id(0), user_id(0),
20 status(ThreadStatusInvalid), detached(false),
21 thread_type(ThreadType::Regular), parent_tid(0), next(0) {
22 name[0] = '\0';
23 atomic_store(&thread_destroyed, 0, memory_order_release);
24}
25
26ThreadContextBase::~ThreadContextBase() {
27 // ThreadContextBase should never be deleted.
28 CHECK(0);
29}
30
31void ThreadContextBase::SetName(const char *new_name) {
32 name[0] = '\0';
33 if (new_name) {
34 internal_strncpy(name, new_name, sizeof(name));
35 name[sizeof(name) - 1] = '\0';
36 }
37}
38
39void ThreadContextBase::SetDead() {
40 CHECK(status == ThreadStatusRunning ||
41 status == ThreadStatusFinished);
42 status = ThreadStatusDead;
43 user_id = 0;
44 OnDead();
45}
46
47void ThreadContextBase::SetDestroyed() {
48 atomic_store(&thread_destroyed, 1, memory_order_release);
49}
50
51bool ThreadContextBase::GetDestroyed() {
52 return !!atomic_load(&thread_destroyed, memory_order_acquire);
53}
54
55void ThreadContextBase::SetJoined(void *arg) {
56 // FIXME(dvyukov): print message and continue (it's user error).
57 CHECK_EQ(false, detached);
58 CHECK_EQ(ThreadStatusFinished, status);
59 status = ThreadStatusDead;
60 user_id = 0;
61 OnJoined(arg);
62}
63
64void ThreadContextBase::SetFinished() {
65 // ThreadRegistry::FinishThread calls here in ThreadStatusCreated state
66 // for a thread that never actually started. In that case the thread
67 // should go to ThreadStatusFinished regardless of whether it was created
68 // as detached.
69 if (!detached || status == ThreadStatusCreated) status = ThreadStatusFinished;
70 OnFinished();
71}
72
73void ThreadContextBase::SetStarted(tid_t _os_id, ThreadType _thread_type,
74 void *arg) {
75 status = ThreadStatusRunning;
76 os_id = _os_id;
77 thread_type = _thread_type;
78 OnStarted(arg);
79}
80
81void ThreadContextBase::SetCreated(uptr _user_id, u64 _unique_id,
82 bool _detached, u32 _parent_tid, void *arg) {
83 status = ThreadStatusCreated;
84 user_id = _user_id;
85 unique_id = _unique_id;
86 detached = _detached;
87 // Parent tid makes no sense for the main thread.
88 if (tid != 0)
89 parent_tid = _parent_tid;
90 OnCreated(arg);
91}
92
93void ThreadContextBase::Reset() {
94 status = ThreadStatusInvalid;
95 SetName(0);
96 atomic_store(&thread_destroyed, 0, memory_order_release);
97 OnReset();
98}
99
100// ThreadRegistry implementation.
101
102const u32 ThreadRegistry::kUnknownTid = ~0U;
103
104ThreadRegistry::ThreadRegistry(ThreadContextFactory factory, u32 max_threads,
105 u32 thread_quarantine_size, u32 max_reuse)
106 : context_factory_(factory),
107 max_threads_(max_threads),
108 thread_quarantine_size_(thread_quarantine_size),
109 max_reuse_(max_reuse),
110 mtx_(),
111 n_contexts_(0),
112 total_threads_(0),
113 alive_threads_(0),
114 max_alive_threads_(0),
115 running_threads_(0) {
116 threads_ = (ThreadContextBase **)MmapOrDie(max_threads_ * sizeof(threads_[0]),
117 "ThreadRegistry");
118 dead_threads_.clear();
119 invalid_threads_.clear();
120}
121
122void ThreadRegistry::GetNumberOfThreads(uptr *total, uptr *running,
123 uptr *alive) {
124 BlockingMutexLock l(&mtx_);
125 if (total) *total = n_contexts_;
126 if (running) *running = running_threads_;
127 if (alive) *alive = alive_threads_;
128}
129
130uptr ThreadRegistry::GetMaxAliveThreads() {
131 BlockingMutexLock l(&mtx_);
132 return max_alive_threads_;
133}
134
135u32 ThreadRegistry::CreateThread(uptr user_id, bool detached, u32 parent_tid,
136 void *arg) {
137 BlockingMutexLock l(&mtx_);
138 u32 tid = kUnknownTid;
139 ThreadContextBase *tctx = QuarantinePop();
140 if (tctx) {
141 tid = tctx->tid;
142 } else if (n_contexts_ < max_threads_) {
143 // Allocate new thread context and tid.
144 tid = n_contexts_++;
145 tctx = context_factory_(tid);
146 threads_[tid] = tctx;
147 } else {
148#if !SANITIZER_GO
149 Report("%s: Thread limit (%u threads) exceeded. Dying.\n",
150 SanitizerToolName, max_threads_);
151#else
152 Printf("race: limit on %u simultaneously alive goroutines is exceeded,"
153 " dying\n", max_threads_);
154#endif
155 Die();
156 }
157 CHECK_NE(tctx, 0);
158 CHECK_NE(tid, kUnknownTid);
159 CHECK_LT(tid, max_threads_);
160 CHECK_EQ(tctx->status, ThreadStatusInvalid);
161 alive_threads_++;
162 if (max_alive_threads_ < alive_threads_) {
163 max_alive_threads_++;
164 CHECK_EQ(alive_threads_, max_alive_threads_);
165 }
166 tctx->SetCreated(user_id, total_threads_++, detached,
167 parent_tid, arg);
168 return tid;
169}
170
171void ThreadRegistry::RunCallbackForEachThreadLocked(ThreadCallback cb,
172 void *arg) {
173 CheckLocked();
174 for (u32 tid = 0; tid < n_contexts_; tid++) {
175 ThreadContextBase *tctx = threads_[tid];
176 if (tctx == 0)
177 continue;
178 cb(tctx, arg);
179 }
180}
181
182u32 ThreadRegistry::FindThread(FindThreadCallback cb, void *arg) {
183 BlockingMutexLock l(&mtx_);
184 for (u32 tid = 0; tid < n_contexts_; tid++) {
185 ThreadContextBase *tctx = threads_[tid];
186 if (tctx != 0 && cb(tctx, arg))
187 return tctx->tid;
188 }
189 return kUnknownTid;
190}
191
192ThreadContextBase *
193ThreadRegistry::FindThreadContextLocked(FindThreadCallback cb, void *arg) {
194 CheckLocked();
195 for (u32 tid = 0; tid < n_contexts_; tid++) {
196 ThreadContextBase *tctx = threads_[tid];
197 if (tctx != 0 && cb(tctx, arg))
198 return tctx;
199 }
200 return 0;
201}
202
203static bool FindThreadContextByOsIdCallback(ThreadContextBase *tctx,
204 void *arg) {
205 return (tctx->os_id == (uptr)arg && tctx->status != ThreadStatusInvalid &&
206 tctx->status != ThreadStatusDead);
207}
208
209ThreadContextBase *ThreadRegistry::FindThreadContextByOsIDLocked(tid_t os_id) {
210 return FindThreadContextLocked(FindThreadContextByOsIdCallback,
211 (void *)os_id);
212}
213
214void ThreadRegistry::SetThreadName(u32 tid, const char *name) {
215 BlockingMutexLock l(&mtx_);
216 CHECK_LT(tid, n_contexts_);
217 ThreadContextBase *tctx = threads_[tid];
218 CHECK_NE(tctx, 0);
219 CHECK_EQ(SANITIZER_FUCHSIA ? ThreadStatusCreated : ThreadStatusRunning,
220 tctx->status);
221 tctx->SetName(name);
222}
223
224void ThreadRegistry::SetThreadNameByUserId(uptr user_id, const char *name) {
225 BlockingMutexLock l(&mtx_);
226 for (u32 tid = 0; tid < n_contexts_; tid++) {
227 ThreadContextBase *tctx = threads_[tid];
228 if (tctx != 0 && tctx->user_id == user_id &&
229 tctx->status != ThreadStatusInvalid) {
230 tctx->SetName(name);
231 return;
232 }
233 }
234}
235
236void ThreadRegistry::DetachThread(u32 tid, void *arg) {
237 BlockingMutexLock l(&mtx_);
238 CHECK_LT(tid, n_contexts_);
239 ThreadContextBase *tctx = threads_[tid];
240 CHECK_NE(tctx, 0);
241 if (tctx->status == ThreadStatusInvalid) {
242 Report("%s: Detach of non-existent thread\n", SanitizerToolName);
243 return;
244 }
245 tctx->OnDetached(arg);
246 if (tctx->status == ThreadStatusFinished) {
247 tctx->SetDead();
248 QuarantinePush(tctx);
249 } else {
250 tctx->detached = true;
251 }
252}
253
254void ThreadRegistry::JoinThread(u32 tid, void *arg) {
255 bool destroyed = false;
256 do {
257 {
258 BlockingMutexLock l(&mtx_);
259 CHECK_LT(tid, n_contexts_);
260 ThreadContextBase *tctx = threads_[tid];
261 CHECK_NE(tctx, 0);
262 if (tctx->status == ThreadStatusInvalid) {
263 Report("%s: Join of non-existent thread\n", SanitizerToolName);
264 return;
265 }
266 if ((destroyed = tctx->GetDestroyed())) {
267 tctx->SetJoined(arg);
268 QuarantinePush(tctx);
269 }
270 }
271 if (!destroyed)
272 internal_sched_yield();
273 } while (!destroyed);
274}
275
276// Normally this is called when the thread is about to exit. If
277// called in ThreadStatusCreated state, then this thread was never
278// really started. We just did CreateThread for a prospective new
279// thread before trying to create it, and then failed to actually
280// create it, and so never called StartThread.
281void ThreadRegistry::FinishThread(u32 tid) {
282 BlockingMutexLock l(&mtx_);
283 CHECK_GT(alive_threads_, 0);
284 alive_threads_--;
285 CHECK_LT(tid, n_contexts_);
286 ThreadContextBase *tctx = threads_[tid];
287 CHECK_NE(tctx, 0);
288 bool dead = tctx->detached;
289 if (tctx->status == ThreadStatusRunning) {
290 CHECK_GT(running_threads_, 0);
291 running_threads_--;
292 } else {
293 // The thread never really existed.
294 CHECK_EQ(tctx->status, ThreadStatusCreated);
295 dead = true;
296 }
297 tctx->SetFinished();
298 if (dead) {
299 tctx->SetDead();
300 QuarantinePush(tctx);
301 }
302 tctx->SetDestroyed();
303}
304
305void ThreadRegistry::StartThread(u32 tid, tid_t os_id, ThreadType thread_type,
306 void *arg) {
307 BlockingMutexLock l(&mtx_);
308 running_threads_++;
309 CHECK_LT(tid, n_contexts_);
310 ThreadContextBase *tctx = threads_[tid];
311 CHECK_NE(tctx, 0);
312 CHECK_EQ(ThreadStatusCreated, tctx->status);
313 tctx->SetStarted(os_id, thread_type, arg);
314}
315
316void ThreadRegistry::QuarantinePush(ThreadContextBase *tctx) {
317 if (tctx->tid == 0)
318 return; // Don't reuse the main thread. It's a special snowflake.
319 dead_threads_.push_back(tctx);
320 if (dead_threads_.size() <= thread_quarantine_size_)
321 return;
322 tctx = dead_threads_.front();
323 dead_threads_.pop_front();
324 CHECK_EQ(tctx->status, ThreadStatusDead);
325 tctx->Reset();
326 tctx->reuse_count++;
327 if (max_reuse_ > 0 && tctx->reuse_count >= max_reuse_)
328 return;
329 invalid_threads_.push_back(tctx);
330}
331
332ThreadContextBase *ThreadRegistry::QuarantinePop() {
333 if (invalid_threads_.size() == 0)
334 return 0;
335 ThreadContextBase *tctx = invalid_threads_.front();
336 invalid_threads_.pop_front();
337 return tctx;
338}
339
340void ThreadRegistry::SetThreadUserId(u32 tid, uptr user_id) {
341 BlockingMutexLock l(&mtx_);
342 CHECK_LT(tid, n_contexts_);
343 ThreadContextBase *tctx = threads_[tid];
344 CHECK_NE(tctx, 0);
345 CHECK_NE(tctx->status, ThreadStatusInvalid);
346 CHECK_NE(tctx->status, ThreadStatusDead);
347 CHECK_EQ(tctx->user_id, 0);
348 tctx->user_id = user_id;
349}
350
351} // namespace __sanitizer
lib/tsan/sanitizer_common/sanitizer_thread_registry.h created+160
...@@ -0,0 +1,160 @@
1//===-- sanitizer_thread_registry.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// General thread bookkeeping functionality.
12//===----------------------------------------------------------------------===//
13
14#ifndef SANITIZER_THREAD_REGISTRY_H
15#define SANITIZER_THREAD_REGISTRY_H
16
17#include "sanitizer_common.h"
18#include "sanitizer_list.h"
19#include "sanitizer_mutex.h"
20
21namespace __sanitizer {
22
23enum ThreadStatus {
24 ThreadStatusInvalid, // Non-existent thread, data is invalid.
25 ThreadStatusCreated, // Created but not yet running.
26 ThreadStatusRunning, // The thread is currently running.
27 ThreadStatusFinished, // Joinable thread is finished but not yet joined.
28 ThreadStatusDead // Joined, but some info is still available.
29};
30
31enum class ThreadType {
32 Regular, // Normal thread
33 Worker, // macOS Grand Central Dispatch (GCD) worker thread
34 Fiber, // Fiber
35};
36
37// Generic thread context. Specific sanitizer tools may inherit from it.
38// If thread is dead, context may optionally be reused for a new thread.
39class ThreadContextBase {
40 public:
41 explicit ThreadContextBase(u32 tid);
42 ~ThreadContextBase(); // Should never be called.
43
44 const u32 tid; // Thread ID. Main thread should have tid = 0.
45 u64 unique_id; // Unique thread ID.
46 u32 reuse_count; // Number of times this tid was reused.
47 tid_t os_id; // PID (used for reporting).
48 uptr user_id; // Some opaque user thread id (e.g. pthread_t).
49 char name[64]; // As annotated by user.
50
51 ThreadStatus status;
52 bool detached;
53 ThreadType thread_type;
54
55 u32 parent_tid;
56 ThreadContextBase *next; // For storing thread contexts in a list.
57
58 atomic_uint32_t thread_destroyed; // To address race of Joined vs Finished
59
60 void SetName(const char *new_name);
61
62 void SetDead();
63 void SetJoined(void *arg);
64 void SetFinished();
65 void SetStarted(tid_t _os_id, ThreadType _thread_type, void *arg);
66 void SetCreated(uptr _user_id, u64 _unique_id, bool _detached,
67 u32 _parent_tid, void *arg);
68 void Reset();
69
70 void SetDestroyed();
71 bool GetDestroyed();
72
73 // The following methods may be overriden by subclasses.
74 // Some of them take opaque arg that may be optionally be used
75 // by subclasses.
76 virtual void OnDead() {}
77 virtual void OnJoined(void *arg) {}
78 virtual void OnFinished() {}
79 virtual void OnStarted(void *arg) {}
80 virtual void OnCreated(void *arg) {}
81 virtual void OnReset() {}
82 virtual void OnDetached(void *arg) {}
83};
84
85typedef ThreadContextBase* (*ThreadContextFactory)(u32 tid);
86
87class ThreadRegistry {
88 public:
89 static const u32 kUnknownTid;
90
91 ThreadRegistry(ThreadContextFactory factory, u32 max_threads,
92 u32 thread_quarantine_size, u32 max_reuse = 0);
93 void GetNumberOfThreads(uptr *total = nullptr, uptr *running = nullptr,
94 uptr *alive = nullptr);
95 uptr GetMaxAliveThreads();
96
97 void Lock() { mtx_.Lock(); }
98 void CheckLocked() { mtx_.CheckLocked(); }
99 void Unlock() { mtx_.Unlock(); }
100
101 // Should be guarded by ThreadRegistryLock.
102 ThreadContextBase *GetThreadLocked(u32 tid) {
103 DCHECK_LT(tid, n_contexts_);
104 return threads_[tid];
105 }
106
107 u32 CreateThread(uptr user_id, bool detached, u32 parent_tid, void *arg);
108
109 typedef void (*ThreadCallback)(ThreadContextBase *tctx, void *arg);
110 // Invokes callback with a specified arg for each thread context.
111 // Should be guarded by ThreadRegistryLock.
112 void RunCallbackForEachThreadLocked(ThreadCallback cb, void *arg);
113
114 typedef bool (*FindThreadCallback)(ThreadContextBase *tctx, void *arg);
115 // Finds a thread using the provided callback. Returns kUnknownTid if no
116 // thread is found.
117 u32 FindThread(FindThreadCallback cb, void *arg);
118 // Should be guarded by ThreadRegistryLock. Return 0 if no thread
119 // is found.
120 ThreadContextBase *FindThreadContextLocked(FindThreadCallback cb,
121 void *arg);
122 ThreadContextBase *FindThreadContextByOsIDLocked(tid_t os_id);
123
124 void SetThreadName(u32 tid, const char *name);
125 void SetThreadNameByUserId(uptr user_id, const char *name);
126 void DetachThread(u32 tid, void *arg);
127 void JoinThread(u32 tid, void *arg);
128 void FinishThread(u32 tid);
129 void StartThread(u32 tid, tid_t os_id, ThreadType thread_type, void *arg);
130 void SetThreadUserId(u32 tid, uptr user_id);
131
132 private:
133 const ThreadContextFactory context_factory_;
134 const u32 max_threads_;
135 const u32 thread_quarantine_size_;
136 const u32 max_reuse_;
137
138 BlockingMutex mtx_;
139
140 u32 n_contexts_; // Number of created thread contexts,
141 // at most max_threads_.
142 u64 total_threads_; // Total number of created threads. May be greater than
143 // max_threads_ if contexts were reused.
144 uptr alive_threads_; // Created or running.
145 uptr max_alive_threads_;
146 uptr running_threads_;
147
148 ThreadContextBase **threads_; // Array of thread contexts is leaked.
149 IntrusiveList<ThreadContextBase> dead_threads_;
150 IntrusiveList<ThreadContextBase> invalid_threads_;
151
152 void QuarantinePush(ThreadContextBase *tctx);
153 ThreadContextBase *QuarantinePop();
154};
155
156typedef GenericScopedLock<ThreadRegistry> ThreadRegistryLock;
157
158} // namespace __sanitizer
159
160#endif // SANITIZER_THREAD_REGISTRY_H
lib/tsan/sanitizer_common/sanitizer_tls_get_addr.cpp created+154
...@@ -0,0 +1,154 @@
1//===-- sanitizer_tls_get_addr.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// Handle the __tls_get_addr call.
10//
11//===----------------------------------------------------------------------===//
12
13#include "sanitizer_tls_get_addr.h"
14
15#include "sanitizer_flags.h"
16#include "sanitizer_platform_interceptors.h"
17
18namespace __sanitizer {
19#if SANITIZER_INTERCEPT_TLS_GET_ADDR
20
21// The actual parameter that comes to __tls_get_addr
22// is a pointer to a struct with two words in it:
23struct TlsGetAddrParam {
24 uptr dso_id;
25 uptr offset;
26};
27
28// Glibc starting from 2.19 allocates tls using __signal_safe_memalign,
29// which has such header.
30struct Glibc_2_19_tls_header {
31 uptr size;
32 uptr start;
33};
34
35// This must be static TLS
36__attribute__((tls_model("initial-exec")))
37static __thread DTLS dtls;
38
39// Make sure we properly destroy the DTLS objects:
40// this counter should never get too large.
41static atomic_uintptr_t number_of_live_dtls;
42
43static const uptr kDestroyedThread = -1;
44
45static inline void DTLS_Deallocate(DTLS::DTV *dtv, uptr size) {
46 if (!size) return;
47 VReport(2, "__tls_get_addr: DTLS_Deallocate %p %zd\n", dtv, size);
48 UnmapOrDie(dtv, size * sizeof(DTLS::DTV));
49 atomic_fetch_sub(&number_of_live_dtls, 1, memory_order_relaxed);
50}
51
52static inline void DTLS_Resize(uptr new_size) {
53 if (dtls.dtv_size >= new_size) return;
54 new_size = RoundUpToPowerOfTwo(new_size);
55 new_size = Max(new_size, 4096UL / sizeof(DTLS::DTV));
56 DTLS::DTV *new_dtv =
57 (DTLS::DTV *)MmapOrDie(new_size * sizeof(DTLS::DTV), "DTLS_Resize");
58 uptr num_live_dtls =
59 atomic_fetch_add(&number_of_live_dtls, 1, memory_order_relaxed);
60 VReport(2, "__tls_get_addr: DTLS_Resize %p %zd\n", &dtls, num_live_dtls);
61 CHECK_LT(num_live_dtls, 1 << 20);
62 uptr old_dtv_size = dtls.dtv_size;
63 DTLS::DTV *old_dtv = dtls.dtv;
64 if (old_dtv_size)
65 internal_memcpy(new_dtv, dtls.dtv, dtls.dtv_size * sizeof(DTLS::DTV));
66 dtls.dtv = new_dtv;
67 dtls.dtv_size = new_size;
68 if (old_dtv_size)
69 DTLS_Deallocate(old_dtv, old_dtv_size);
70}
71
72void DTLS_Destroy() {
73 if (!common_flags()->intercept_tls_get_addr) return;
74 VReport(2, "__tls_get_addr: DTLS_Destroy %p %zd\n", &dtls, dtls.dtv_size);
75 uptr s = dtls.dtv_size;
76 dtls.dtv_size = kDestroyedThread; // Do this before unmap for AS-safety.
77 DTLS_Deallocate(dtls.dtv, s);
78}
79
80#if defined(__powerpc64__) || defined(__mips__)
81// This is glibc's TLS_DTV_OFFSET:
82// "Dynamic thread vector pointers point 0x8000 past the start of each
83// TLS block."
84static const uptr kDtvOffset = 0x8000;
85#else
86static const uptr kDtvOffset = 0;
87#endif
88
89DTLS::DTV *DTLS_on_tls_get_addr(void *arg_void, void *res,
90 uptr static_tls_begin, uptr static_tls_end) {
91 if (!common_flags()->intercept_tls_get_addr) return 0;
92 TlsGetAddrParam *arg = reinterpret_cast<TlsGetAddrParam *>(arg_void);
93 uptr dso_id = arg->dso_id;
94 if (dtls.dtv_size == kDestroyedThread) return 0;
95 DTLS_Resize(dso_id + 1);
96 if (dtls.dtv[dso_id].beg) return 0;
97 uptr tls_size = 0;
98 uptr tls_beg = reinterpret_cast<uptr>(res) - arg->offset - kDtvOffset;
99 VReport(2, "__tls_get_addr: %p {%p,%p} => %p; tls_beg: %p; sp: %p "
100 "num_live_dtls %zd\n",
101 arg, arg->dso_id, arg->offset, res, tls_beg, &tls_beg,
102 atomic_load(&number_of_live_dtls, memory_order_relaxed));
103 if (dtls.last_memalign_ptr == tls_beg) {
104 tls_size = dtls.last_memalign_size;
105 VReport(2, "__tls_get_addr: glibc <=2.18 suspected; tls={%p,%p}\n",
106 tls_beg, tls_size);
107 } else if (tls_beg >= static_tls_begin && tls_beg < static_tls_end) {
108 // This is the static TLS block which was initialized / unpoisoned at thread
109 // creation.
110 VReport(2, "__tls_get_addr: static tls: %p\n", tls_beg);
111 tls_size = 0;
112 } else if ((tls_beg % 4096) == sizeof(Glibc_2_19_tls_header)) {
113 // We may want to check gnu_get_libc_version().
114 Glibc_2_19_tls_header *header = (Glibc_2_19_tls_header *)tls_beg - 1;
115 tls_size = header->size;
116 tls_beg = header->start;
117 VReport(2, "__tls_get_addr: glibc >=2.19 suspected; tls={%p %p}\n",
118 tls_beg, tls_size);
119 } else {
120 VReport(2, "__tls_get_addr: Can't guess glibc version\n");
121 // This may happen inside the DTOR of main thread, so just ignore it.
122 tls_size = 0;
123 }
124 dtls.dtv[dso_id].beg = tls_beg;
125 dtls.dtv[dso_id].size = tls_size;
126 return dtls.dtv + dso_id;
127}
128
129void DTLS_on_libc_memalign(void *ptr, uptr size) {
130 if (!common_flags()->intercept_tls_get_addr) return;
131 VReport(2, "DTLS_on_libc_memalign: %p %p\n", ptr, size);
132 dtls.last_memalign_ptr = reinterpret_cast<uptr>(ptr);
133 dtls.last_memalign_size = size;
134}
135
136DTLS *DTLS_Get() { return &dtls; }
137
138bool DTLSInDestruction(DTLS *dtls) {
139 return dtls->dtv_size == kDestroyedThread;
140}
141
142#else
143void DTLS_on_libc_memalign(void *ptr, uptr size) {}
144DTLS::DTV *DTLS_on_tls_get_addr(void *arg, void *res,
145 unsigned long, unsigned long) { return 0; }
146DTLS *DTLS_Get() { return 0; }
147void DTLS_Destroy() {}
148bool DTLSInDestruction(DTLS *dtls) {
149 UNREACHABLE("dtls is unsupported on this platform!");
150}
151
152#endif // SANITIZER_INTERCEPT_TLS_GET_ADDR
153
154} // namespace __sanitizer
lib/tsan/sanitizer_common/sanitizer_tls_get_addr.h created+62
...@@ -0,0 +1,62 @@
1//===-- sanitizer_tls_get_addr.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// Handle the __tls_get_addr call.
10//
11// All this magic is specific to glibc and is required to workaround
12// the lack of interface that would tell us about the Dynamic TLS (DTLS).
13// https://sourceware.org/bugzilla/show_bug.cgi?id=16291
14//
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,
20// 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.
25//
26//===----------------------------------------------------------------------===//
27
28#ifndef SANITIZER_TLS_GET_ADDR_H
29#define SANITIZER_TLS_GET_ADDR_H
30
31#include "sanitizer_common.h"
32
33namespace __sanitizer {
34
35struct DTLS {
36 // Array of DTLS chunks for the current Thread.
37 // If beg == 0, the chunk is unused.
38 struct DTV {
39 uptr beg, size;
40 };
41
42 uptr dtv_size;
43 DTV *dtv; // dtv_size elements, allocated by MmapOrDie.
44
45 // Auxiliary fields, don't access them outside sanitizer_tls_get_addr.cpp
46 uptr last_memalign_size;
47 uptr last_memalign_ptr;
48};
49
50// Returns pointer and size of a linker-allocated TLS block.
51// Each block is returned exactly once.
52DTLS::DTV *DTLS_on_tls_get_addr(void *arg, void *res, uptr static_tls_begin,
53 uptr static_tls_end);
54void DTLS_on_libc_memalign(void *ptr, uptr size);
55DTLS *DTLS_Get();
56void DTLS_Destroy(); // Make sure to call this before the thread is destroyed.
57// Returns true if DTLS of suspended thread is in destruction process.
58bool DTLSInDestruction(DTLS *dtls);
59
60} // namespace __sanitizer
61
62#endif // SANITIZER_TLS_GET_ADDR_H
lib/tsan/sanitizer_common/sanitizer_type_traits.cpp created+20
...@@ -0,0 +1,20 @@
1//===-- sanitizer_type_traits.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// Implements a subset of C++ type traits. This is so we can avoid depending
10// on system C++ headers.
11//
12//===----------------------------------------------------------------------===//
13#include "sanitizer_type_traits.h"
14
15namespace __sanitizer {
16
17const bool true_type::value;
18const bool false_type::value;
19
20} // namespace __sanitizer
lib/tsan/sanitizer_common/sanitizer_type_traits.h created+62
...@@ -0,0 +1,62 @@
1//===-- sanitizer_type_traits.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// Implements a subset of C++ type traits. This is so we can avoid depending
10// on system C++ headers.
11//
12//===----------------------------------------------------------------------===//
13#ifndef SANITIZER_TYPE_TRAITS_H
14#define SANITIZER_TYPE_TRAITS_H
15
16namespace __sanitizer {
17
18struct true_type {
19 static const bool value = true;
20};
21
22struct false_type {
23 static const bool value = false;
24};
25
26// is_same<T, U>
27//
28// Type trait to compare if types are the same.
29// E.g.
30//
31// ```
32// is_same<int,int>::value - True
33// is_same<int,char>::value - False
34// ```
35template <typename T, typename U>
36struct is_same : public false_type {};
37
38template <typename T>
39struct is_same<T, T> : public true_type {};
40
41// conditional<B, T, F>
42//
43// Defines type as T if B is true or as F otherwise.
44// E.g. the following is true
45//
46// ```
47// is_same<int, conditional<true, int, double>::type>::value
48// is_same<double, conditional<false, int, double>::type>::value
49// ```
50template <bool B, class T, class F>
51struct conditional {
52 using type = T;
53};
54
55template <class T, class F>
56struct conditional<false, T, F> {
57 using type = F;
58};
59
60} // namespace __sanitizer
61
62#endif
lib/tsan/sanitizer_common/sanitizer_vector.h created+124
...@@ -0,0 +1,124 @@
1//===-- sanitizer_vector.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 sanitizers run-time libraries.
10//
11//===----------------------------------------------------------------------===//
12
13// Low-fat STL-like vector container.
14
15#ifndef SANITIZER_VECTOR_H
16#define SANITIZER_VECTOR_H
17
18#include "sanitizer_common/sanitizer_allocator_internal.h"
19#include "sanitizer_common/sanitizer_libc.h"
20
21namespace __sanitizer {
22
23template<typename T>
24class Vector {
25 public:
26 Vector() : begin_(), end_(), last_() {}
27
28 ~Vector() {
29 if (begin_)
30 InternalFree(begin_);
31 }
32
33 void Reset() {
34 if (begin_)
35 InternalFree(begin_);
36 begin_ = 0;
37 end_ = 0;
38 last_ = 0;
39 }
40
41 uptr Size() const {
42 return end_ - begin_;
43 }
44
45 T &operator[](uptr i) {
46 DCHECK_LT(i, end_ - begin_);
47 return begin_[i];
48 }
49
50 const T &operator[](uptr i) const {
51 DCHECK_LT(i, end_ - begin_);
52 return begin_[i];
53 }
54
55 T *PushBack() {
56 EnsureSize(Size() + 1);
57 T *p = &end_[-1];
58 internal_memset(p, 0, sizeof(*p));
59 return p;
60 }
61
62 T *PushBack(const T& v) {
63 EnsureSize(Size() + 1);
64 T *p = &end_[-1];
65 internal_memcpy(p, &v, sizeof(*p));
66 return p;
67 }
68
69 void PopBack() {
70 DCHECK_GT(end_, begin_);
71 end_--;
72 }
73
74 void Resize(uptr size) {
75 if (size == 0) {
76 end_ = begin_;
77 return;
78 }
79 uptr old_size = Size();
80 if (size <= old_size) {
81 end_ = begin_ + size;
82 return;
83 }
84 EnsureSize(size);
85 if (old_size < size) {
86 for (uptr i = old_size; i < size; i++)
87 internal_memset(&begin_[i], 0, sizeof(begin_[i]));
88 }
89 }
90
91 private:
92 T *begin_;
93 T *end_;
94 T *last_;
95
96 void EnsureSize(uptr size) {
97 if (size <= Size())
98 return;
99 if (size <= (uptr)(last_ - begin_)) {
100 end_ = begin_ + size;
101 return;
102 }
103 uptr cap0 = last_ - begin_;
104 uptr cap = cap0 * 5 / 4; // 25% growth
105 if (cap == 0)
106 cap = 16;
107 if (cap < size)
108 cap = size;
109 T *p = (T*)InternalAlloc(cap * sizeof(T));
110 if (cap0) {
111 internal_memcpy(p, begin_, cap0 * sizeof(T));
112 InternalFree(begin_);
113 }
114 begin_ = p;
115 end_ = begin_ + size;
116 last_ = begin_ + cap;
117 }
118
119 Vector(const Vector&);
120 void operator=(const Vector&);
121};
122} // namespace __sanitizer
123
124#endif // #ifndef SANITIZER_VECTOR_H
lib/tsan/sanitizer_common/sanitizer_win.cpp created+1129
...@@ -0,0 +1,1129 @@
1//===-- sanitizer_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// This file is shared between AddressSanitizer and ThreadSanitizer
10// run-time libraries and implements windows-specific functions from
11// sanitizer_libc.h.
12//===----------------------------------------------------------------------===//
13
14#include "sanitizer_platform.h"
15#if SANITIZER_WINDOWS
16
17#define WIN32_LEAN_AND_MEAN
18#define NOGDI
19#include <windows.h>
20#include <io.h>
21#include <psapi.h>
22#include <stdlib.h>
23
24#include "sanitizer_common.h"
25#include "sanitizer_file.h"
26#include "sanitizer_libc.h"
27#include "sanitizer_mutex.h"
28#include "sanitizer_placement_new.h"
29#include "sanitizer_win_defs.h"
30
31#if defined(PSAPI_VERSION) && PSAPI_VERSION == 1
32#pragma comment(lib, "psapi")
33#endif
34#if SANITIZER_WIN_TRACE
35#include <traceloggingprovider.h>
36// Windows trace logging provider init
37#pragma comment(lib, "advapi32.lib")
38TRACELOGGING_DECLARE_PROVIDER(g_asan_provider);
39// GUID must be the same in utils/AddressSanitizerLoggingProvider.wprp
40TRACELOGGING_DEFINE_PROVIDER(g_asan_provider, "AddressSanitizerLoggingProvider",
41 (0x6c6c766d, 0x3846, 0x4e6a, 0xa4, 0xfb, 0x5b,
42 0x53, 0x0b, 0xd0, 0xf3, 0xfa));
43#else
44#define TraceLoggingUnregister(x)
45#endif
46
47// A macro to tell the compiler that this part of the code cannot be reached,
48// if the compiler supports this feature. Since we're using this in
49// code that is called when terminating the process, the expansion of the
50// macro should not terminate the process to avoid infinite recursion.
51#if defined(__clang__)
52# define BUILTIN_UNREACHABLE() __builtin_unreachable()
53#elif defined(__GNUC__) && \
54 (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
55# define BUILTIN_UNREACHABLE() __builtin_unreachable()
56#elif defined(_MSC_VER)
57# define BUILTIN_UNREACHABLE() __assume(0)
58#else
59# define BUILTIN_UNREACHABLE()
60#endif
61
62namespace __sanitizer {
63
64#include "sanitizer_syscall_generic.inc"
65
66// --------------------- sanitizer_common.h
67uptr GetPageSize() {
68 SYSTEM_INFO si;
69 GetSystemInfo(&si);
70 return si.dwPageSize;
71}
72
73uptr GetMmapGranularity() {
74 SYSTEM_INFO si;
75 GetSystemInfo(&si);
76 return si.dwAllocationGranularity;
77}
78
79uptr GetMaxUserVirtualAddress() {
80 SYSTEM_INFO si;
81 GetSystemInfo(&si);
82 return (uptr)si.lpMaximumApplicationAddress;
83}
84
85uptr GetMaxVirtualAddress() {
86 return GetMaxUserVirtualAddress();
87}
88
89bool FileExists(const char *filename) {
90 return ::GetFileAttributesA(filename) != INVALID_FILE_ATTRIBUTES;
91}
92
93uptr internal_getpid() {
94 return GetProcessId(GetCurrentProcess());
95}
96
97int internal_dlinfo(void *handle, int request, void *p) {
98 UNIMPLEMENTED();
99}
100
101// In contrast to POSIX, on Windows GetCurrentThreadId()
102// returns a system-unique identifier.
103tid_t GetTid() {
104 return GetCurrentThreadId();
105}
106
107uptr GetThreadSelf() {
108 return GetTid();
109}
110
111#if !SANITIZER_GO
112void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
113 uptr *stack_bottom) {
114 CHECK(stack_top);
115 CHECK(stack_bottom);
116 MEMORY_BASIC_INFORMATION mbi;
117 CHECK_NE(VirtualQuery(&mbi /* on stack */, &mbi, sizeof(mbi)), 0);
118 // FIXME: is it possible for the stack to not be a single allocation?
119 // Are these values what ASan expects to get (reserved, not committed;
120 // including stack guard page) ?
121 *stack_top = (uptr)mbi.BaseAddress + mbi.RegionSize;
122 *stack_bottom = (uptr)mbi.AllocationBase;
123}
124#endif // #if !SANITIZER_GO
125
126void *MmapOrDie(uptr size, const char *mem_type, bool raw_report) {
127 void *rv = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
128 if (rv == 0)
129 ReportMmapFailureAndDie(size, mem_type, "allocate",
130 GetLastError(), raw_report);
131 return rv;
132}
133
134void UnmapOrDie(void *addr, uptr size) {
135 if (!size || !addr)
136 return;
137
138 MEMORY_BASIC_INFORMATION mbi;
139 CHECK(VirtualQuery(addr, &mbi, sizeof(mbi)));
140
141 // MEM_RELEASE can only be used to unmap whole regions previously mapped with
142 // VirtualAlloc. So we first try MEM_RELEASE since it is better, and if that
143 // fails try MEM_DECOMMIT.
144 if (VirtualFree(addr, 0, MEM_RELEASE) == 0) {
145 if (VirtualFree(addr, size, MEM_DECOMMIT) == 0) {
146 Report("ERROR: %s failed to "
147 "deallocate 0x%zx (%zd) bytes at address %p (error code: %d)\n",
148 SanitizerToolName, size, size, addr, GetLastError());
149 CHECK("unable to unmap" && 0);
150 }
151 }
152}
153
154static void *ReturnNullptrOnOOMOrDie(uptr size, const char *mem_type,
155 const char *mmap_type) {
156 error_t last_error = GetLastError();
157 if (last_error == ERROR_NOT_ENOUGH_MEMORY)
158 return nullptr;
159 ReportMmapFailureAndDie(size, mem_type, mmap_type, last_error);
160}
161
162void *MmapOrDieOnFatalError(uptr size, const char *mem_type) {
163 void *rv = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
164 if (rv == 0)
165 return ReturnNullptrOnOOMOrDie(size, mem_type, "allocate");
166 return rv;
167}
168
169// We want to map a chunk of address space aligned to 'alignment'.
170void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment,
171 const char *mem_type) {
172 CHECK(IsPowerOfTwo(size));
173 CHECK(IsPowerOfTwo(alignment));
174
175 // Windows will align our allocations to at least 64K.
176 alignment = Max(alignment, GetMmapGranularity());
177
178 uptr mapped_addr =
179 (uptr)VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
180 if (!mapped_addr)
181 return ReturnNullptrOnOOMOrDie(size, mem_type, "allocate aligned");
182
183 // If we got it right on the first try, return. Otherwise, unmap it and go to
184 // the slow path.
185 if (IsAligned(mapped_addr, alignment))
186 return (void*)mapped_addr;
187 if (VirtualFree((void *)mapped_addr, 0, MEM_RELEASE) == 0)
188 ReportMmapFailureAndDie(size, mem_type, "deallocate", GetLastError());
189
190 // If we didn't get an aligned address, overallocate, find an aligned address,
191 // unmap, and try to allocate at that aligned address.
192 int retries = 0;
193 const int kMaxRetries = 10;
194 for (; retries < kMaxRetries &&
195 (mapped_addr == 0 || !IsAligned(mapped_addr, alignment));
196 retries++) {
197 // Overallocate size + alignment bytes.
198 mapped_addr =
199 (uptr)VirtualAlloc(0, size + alignment, MEM_RESERVE, PAGE_NOACCESS);
200 if (!mapped_addr)
201 return ReturnNullptrOnOOMOrDie(size, mem_type, "allocate aligned");
202
203 // Find the aligned address.
204 uptr aligned_addr = RoundUpTo(mapped_addr, alignment);
205
206 // Free the overallocation.
207 if (VirtualFree((void *)mapped_addr, 0, MEM_RELEASE) == 0)
208 ReportMmapFailureAndDie(size, mem_type, "deallocate", GetLastError());
209
210 // Attempt to allocate exactly the number of bytes we need at the aligned
211 // address. This may fail for a number of reasons, in which case we continue
212 // the loop.
213 mapped_addr = (uptr)VirtualAlloc((void *)aligned_addr, size,
214 MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
215 }
216
217 // Fail if we can't make this work quickly.
218 if (retries == kMaxRetries && mapped_addr == 0)
219 return ReturnNullptrOnOOMOrDie(size, mem_type, "allocate aligned");
220
221 return (void *)mapped_addr;
222}
223
224bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name) {
225 // FIXME: is this really "NoReserve"? On Win32 this does not matter much,
226 // but on Win64 it does.
227 (void)name; // unsupported
228#if !SANITIZER_GO && SANITIZER_WINDOWS64
229 // On asan/Windows64, use MEM_COMMIT would result in error
230 // 1455:ERROR_COMMITMENT_LIMIT.
231 // Asan uses exception handler to commit page on demand.
232 void *p = VirtualAlloc((LPVOID)fixed_addr, size, MEM_RESERVE, PAGE_READWRITE);
233#else
234 void *p = VirtualAlloc((LPVOID)fixed_addr, size, MEM_RESERVE | MEM_COMMIT,
235 PAGE_READWRITE);
236#endif
237 if (p == 0) {
238 Report("ERROR: %s failed to "
239 "allocate %p (%zd) bytes at %p (error code: %d)\n",
240 SanitizerToolName, size, size, fixed_addr, GetLastError());
241 return false;
242 }
243 return true;
244}
245
246bool MmapFixedSuperNoReserve(uptr fixed_addr, uptr size, const char *name) {
247 // FIXME: Windows support large pages too. Might be worth checking
248 return MmapFixedNoReserve(fixed_addr, size, name);
249}
250
251// Memory space mapped by 'MmapFixedOrDie' must have been reserved by
252// 'MmapFixedNoAccess'.
253void *MmapFixedOrDie(uptr fixed_addr, uptr size, const char *name) {
254 void *p = VirtualAlloc((LPVOID)fixed_addr, size,
255 MEM_COMMIT, PAGE_READWRITE);
256 if (p == 0) {
257 char mem_type[30];
258 internal_snprintf(mem_type, sizeof(mem_type), "memory at address 0x%zx",
259 fixed_addr);
260 ReportMmapFailureAndDie(size, mem_type, "allocate", GetLastError());
261 }
262 return p;
263}
264
265// Uses fixed_addr for now.
266// Will use offset instead once we've implemented this function for real.
267uptr ReservedAddressRange::Map(uptr fixed_addr, uptr size, const char *name) {
268 return reinterpret_cast<uptr>(MmapFixedOrDieOnFatalError(fixed_addr, size));
269}
270
271uptr ReservedAddressRange::MapOrDie(uptr fixed_addr, uptr size,
272 const char *name) {
273 return reinterpret_cast<uptr>(MmapFixedOrDie(fixed_addr, size));
274}
275
276void ReservedAddressRange::Unmap(uptr addr, uptr size) {
277 // Only unmap if it covers the entire range.
278 CHECK((addr == reinterpret_cast<uptr>(base_)) && (size == size_));
279 // We unmap the whole range, just null out the base.
280 base_ = nullptr;
281 size_ = 0;
282 UnmapOrDie(reinterpret_cast<void*>(addr), size);
283}
284
285void *MmapFixedOrDieOnFatalError(uptr fixed_addr, uptr size, const char *name) {
286 void *p = VirtualAlloc((LPVOID)fixed_addr, size,
287 MEM_COMMIT, PAGE_READWRITE);
288 if (p == 0) {
289 char mem_type[30];
290 internal_snprintf(mem_type, sizeof(mem_type), "memory at address 0x%zx",
291 fixed_addr);
292 return ReturnNullptrOnOOMOrDie(size, mem_type, "allocate");
293 }
294 return p;
295}
296
297void *MmapNoReserveOrDie(uptr size, const char *mem_type) {
298 // FIXME: make this really NoReserve?
299 return MmapOrDie(size, mem_type);
300}
301
302uptr ReservedAddressRange::Init(uptr size, const char *name, uptr fixed_addr) {
303 base_ = fixed_addr ? MmapFixedNoAccess(fixed_addr, size) : MmapNoAccess(size);
304 size_ = size;
305 name_ = name;
306 (void)os_handle_; // unsupported
307 return reinterpret_cast<uptr>(base_);
308}
309
310
311void *MmapFixedNoAccess(uptr fixed_addr, uptr size, const char *name) {
312 (void)name; // unsupported
313 void *res = VirtualAlloc((LPVOID)fixed_addr, size,
314 MEM_RESERVE, PAGE_NOACCESS);
315 if (res == 0)
316 Report("WARNING: %s failed to "
317 "mprotect %p (%zd) bytes at %p (error code: %d)\n",
318 SanitizerToolName, size, size, fixed_addr, GetLastError());
319 return res;
320}
321
322void *MmapNoAccess(uptr size) {
323 void *res = VirtualAlloc(nullptr, size, MEM_RESERVE, PAGE_NOACCESS);
324 if (res == 0)
325 Report("WARNING: %s failed to "
326 "mprotect %p (%zd) bytes (error code: %d)\n",
327 SanitizerToolName, size, size, GetLastError());
328 return res;
329}
330
331bool MprotectNoAccess(uptr addr, uptr size) {
332 DWORD old_protection;
333 return VirtualProtect((LPVOID)addr, size, PAGE_NOACCESS, &old_protection);
334}
335
336void ReleaseMemoryPagesToOS(uptr beg, uptr end) {
337 // This is almost useless on 32-bits.
338 // FIXME: add madvise-analog when we move to 64-bits.
339}
340
341void SetShadowRegionHugePageMode(uptr addr, uptr size) {
342 // FIXME: probably similar to ReleaseMemoryToOS.
343}
344
345bool DontDumpShadowMemory(uptr addr, uptr length) {
346 // This is almost useless on 32-bits.
347 // FIXME: add madvise-analog when we move to 64-bits.
348 return true;
349}
350
351uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,
352 uptr *largest_gap_found,
353 uptr *max_occupied_addr) {
354 uptr address = 0;
355 while (true) {
356 MEMORY_BASIC_INFORMATION info;
357 if (!::VirtualQuery((void*)address, &info, sizeof(info)))
358 return 0;
359
360 if (info.State == MEM_FREE) {
361 uptr shadow_address = RoundUpTo((uptr)info.BaseAddress + left_padding,
362 alignment);
363 if (shadow_address + size < (uptr)info.BaseAddress + info.RegionSize)
364 return shadow_address;
365 }
366
367 // Move to the next region.
368 address = (uptr)info.BaseAddress + info.RegionSize;
369 }
370 return 0;
371}
372
373bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) {
374 MEMORY_BASIC_INFORMATION mbi;
375 CHECK(VirtualQuery((void *)range_start, &mbi, sizeof(mbi)));
376 return mbi.Protect == PAGE_NOACCESS &&
377 (uptr)mbi.BaseAddress + mbi.RegionSize >= range_end;
378}
379
380void *MapFileToMemory(const char *file_name, uptr *buff_size) {
381 UNIMPLEMENTED();
382}
383
384void *MapWritableFileToMemory(void *addr, uptr size, fd_t fd, OFF_T offset) {
385 UNIMPLEMENTED();
386}
387
388static const int kMaxEnvNameLength = 128;
389static const DWORD kMaxEnvValueLength = 32767;
390
391namespace {
392
393struct EnvVariable {
394 char name[kMaxEnvNameLength];
395 char value[kMaxEnvValueLength];
396};
397
398} // namespace
399
400static const int kEnvVariables = 5;
401static EnvVariable env_vars[kEnvVariables];
402static int num_env_vars;
403
404const char *GetEnv(const char *name) {
405 // Note: this implementation caches the values of the environment variables
406 // and limits their quantity.
407 for (int i = 0; i < num_env_vars; i++) {
408 if (0 == internal_strcmp(name, env_vars[i].name))
409 return env_vars[i].value;
410 }
411 CHECK_LT(num_env_vars, kEnvVariables);
412 DWORD rv = GetEnvironmentVariableA(name, env_vars[num_env_vars].value,
413 kMaxEnvValueLength);
414 if (rv > 0 && rv < kMaxEnvValueLength) {
415 CHECK_LT(internal_strlen(name), kMaxEnvNameLength);
416 internal_strncpy(env_vars[num_env_vars].name, name, kMaxEnvNameLength);
417 num_env_vars++;
418 return env_vars[num_env_vars - 1].value;
419 }
420 return 0;
421}
422
423const char *GetPwd() {
424 UNIMPLEMENTED();
425}
426
427u32 GetUid() {
428 UNIMPLEMENTED();
429}
430
431namespace {
432struct ModuleInfo {
433 const char *filepath;
434 uptr base_address;
435 uptr end_address;
436};
437
438#if !SANITIZER_GO
439int CompareModulesBase(const void *pl, const void *pr) {
440 const ModuleInfo *l = (const ModuleInfo *)pl, *r = (const ModuleInfo *)pr;
441 if (l->base_address < r->base_address)
442 return -1;
443 return l->base_address > r->base_address;
444}
445#endif
446} // namespace
447
448#if !SANITIZER_GO
449void DumpProcessMap() {
450 Report("Dumping process modules:\n");
451 ListOfModules modules;
452 modules.init();
453 uptr num_modules = modules.size();
454
455 InternalMmapVector<ModuleInfo> module_infos(num_modules);
456 for (size_t i = 0; i < num_modules; ++i) {
457 module_infos[i].filepath = modules[i].full_name();
458 module_infos[i].base_address = modules[i].ranges().front()->beg;
459 module_infos[i].end_address = modules[i].ranges().back()->end;
460 }
461 qsort(module_infos.data(), num_modules, sizeof(ModuleInfo),
462 CompareModulesBase);
463
464 for (size_t i = 0; i < num_modules; ++i) {
465 const ModuleInfo &mi = module_infos[i];
466 if (mi.end_address != 0) {
467 Printf("\t%p-%p %s\n", mi.base_address, mi.end_address,
468 mi.filepath[0] ? mi.filepath : "[no name]");
469 } else if (mi.filepath[0]) {
470 Printf("\t??\?-??? %s\n", mi.filepath);
471 } else {
472 Printf("\t???\n");
473 }
474 }
475}
476#endif
477
478void PrintModuleMap() { }
479
480void DisableCoreDumperIfNecessary() {
481 // Do nothing.
482}
483
484void ReExec() {
485 UNIMPLEMENTED();
486}
487
488void PlatformPrepareForSandboxing(__sanitizer_sandbox_arguments *args) {}
489
490bool StackSizeIsUnlimited() {
491 UNIMPLEMENTED();
492}
493
494void SetStackSizeLimitInBytes(uptr limit) {
495 UNIMPLEMENTED();
496}
497
498bool AddressSpaceIsUnlimited() {
499 UNIMPLEMENTED();
500}
501
502void SetAddressSpaceUnlimited() {
503 UNIMPLEMENTED();
504}
505
506bool IsPathSeparator(const char c) {
507 return c == '\\' || c == '/';
508}
509
510static bool IsAlpha(char c) {
511 c = ToLower(c);
512 return c >= 'a' && c <= 'z';
513}
514
515bool IsAbsolutePath(const char *path) {
516 return path != nullptr && IsAlpha(path[0]) && path[1] == ':' &&
517 IsPathSeparator(path[2]);
518}
519
520void SleepForSeconds(int seconds) {
521 Sleep(seconds * 1000);
522}
523
524void SleepForMillis(int millis) {
525 Sleep(millis);
526}
527
528u64 NanoTime() {
529 static LARGE_INTEGER frequency = {};
530 LARGE_INTEGER counter;
531 if (UNLIKELY(frequency.QuadPart == 0)) {
532 QueryPerformanceFrequency(&frequency);
533 CHECK_NE(frequency.QuadPart, 0);
534 }
535 QueryPerformanceCounter(&counter);
536 counter.QuadPart *= 1000ULL * 1000000ULL;
537 counter.QuadPart /= frequency.QuadPart;
538 return counter.QuadPart;
539}
540
541u64 MonotonicNanoTime() { return NanoTime(); }
542
543void Abort() {
544 internal__exit(3);
545}
546
547#if !SANITIZER_GO
548// Read the file to extract the ImageBase field from the PE header. If ASLR is
549// disabled and this virtual address is available, the loader will typically
550// load the image at this address. Therefore, we call it the preferred base. Any
551// addresses in the DWARF typically assume that the object has been loaded at
552// this address.
553static uptr GetPreferredBase(const char *modname) {
554 fd_t fd = OpenFile(modname, RdOnly, nullptr);
555 if (fd == kInvalidFd)
556 return 0;
557 FileCloser closer(fd);
558
559 // Read just the DOS header.
560 IMAGE_DOS_HEADER dos_header;
561 uptr bytes_read;
562 if (!ReadFromFile(fd, &dos_header, sizeof(dos_header), &bytes_read) ||
563 bytes_read != sizeof(dos_header))
564 return 0;
565
566 // The file should start with the right signature.
567 if (dos_header.e_magic != IMAGE_DOS_SIGNATURE)
568 return 0;
569
570 // The layout at e_lfanew is:
571 // "PE\0\0"
572 // IMAGE_FILE_HEADER
573 // IMAGE_OPTIONAL_HEADER
574 // Seek to e_lfanew and read all that data.
575 char buf[4 + sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_OPTIONAL_HEADER)];
576 if (::SetFilePointer(fd, dos_header.e_lfanew, nullptr, FILE_BEGIN) ==
577 INVALID_SET_FILE_POINTER)
578 return 0;
579 if (!ReadFromFile(fd, &buf[0], sizeof(buf), &bytes_read) ||
580 bytes_read != sizeof(buf))
581 return 0;
582
583 // Check for "PE\0\0" before the PE header.
584 char *pe_sig = &buf[0];
585 if (internal_memcmp(pe_sig, "PE\0\0", 4) != 0)
586 return 0;
587
588 // Skip over IMAGE_FILE_HEADER. We could do more validation here if we wanted.
589 IMAGE_OPTIONAL_HEADER *pe_header =
590 (IMAGE_OPTIONAL_HEADER *)(pe_sig + 4 + sizeof(IMAGE_FILE_HEADER));
591
592 // Check for more magic in the PE header.
593 if (pe_header->Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)
594 return 0;
595
596 // Finally, return the ImageBase.
597 return (uptr)pe_header->ImageBase;
598}
599
600void ListOfModules::init() {
601 clearOrInit();
602 HANDLE cur_process = GetCurrentProcess();
603
604 // Query the list of modules. Start by assuming there are no more than 256
605 // modules and retry if that's not sufficient.
606 HMODULE *hmodules = 0;
607 uptr modules_buffer_size = sizeof(HMODULE) * 256;
608 DWORD bytes_required;
609 while (!hmodules) {
610 hmodules = (HMODULE *)MmapOrDie(modules_buffer_size, __FUNCTION__);
611 CHECK(EnumProcessModules(cur_process, hmodules, modules_buffer_size,
612 &bytes_required));
613 if (bytes_required > modules_buffer_size) {
614 // Either there turned out to be more than 256 hmodules, or new hmodules
615 // could have loaded since the last try. Retry.
616 UnmapOrDie(hmodules, modules_buffer_size);
617 hmodules = 0;
618 modules_buffer_size = bytes_required;
619 }
620 }
621
622 // |num_modules| is the number of modules actually present,
623 size_t num_modules = bytes_required / sizeof(HMODULE);
624 for (size_t i = 0; i < num_modules; ++i) {
625 HMODULE handle = hmodules[i];
626 MODULEINFO mi;
627 if (!GetModuleInformation(cur_process, handle, &mi, sizeof(mi)))
628 continue;
629
630 // Get the UTF-16 path and convert to UTF-8.
631 wchar_t modname_utf16[kMaxPathLength];
632 int modname_utf16_len =
633 GetModuleFileNameW(handle, modname_utf16, kMaxPathLength);
634 if (modname_utf16_len == 0)
635 modname_utf16[0] = '\0';
636 char module_name[kMaxPathLength];
637 int module_name_len =
638 ::WideCharToMultiByte(CP_UTF8, 0, modname_utf16, modname_utf16_len + 1,
639 &module_name[0], kMaxPathLength, NULL, NULL);
640 module_name[module_name_len] = '\0';
641
642 uptr base_address = (uptr)mi.lpBaseOfDll;
643 uptr end_address = (uptr)mi.lpBaseOfDll + mi.SizeOfImage;
644
645 // Adjust the base address of the module so that we get a VA instead of an
646 // RVA when computing the module offset. This helps llvm-symbolizer find the
647 // right DWARF CU. In the common case that the image is loaded at it's
648 // preferred address, we will now print normal virtual addresses.
649 uptr preferred_base = GetPreferredBase(&module_name[0]);
650 uptr adjusted_base = base_address - preferred_base;
651
652 LoadedModule cur_module;
653 cur_module.set(module_name, adjusted_base);
654 // We add the whole module as one single address range.
655 cur_module.addAddressRange(base_address, end_address, /*executable*/ true,
656 /*writable*/ true);
657 modules_.push_back(cur_module);
658 }
659 UnmapOrDie(hmodules, modules_buffer_size);
660}
661
662void ListOfModules::fallbackInit() { clear(); }
663
664// We can't use atexit() directly at __asan_init time as the CRT is not fully
665// initialized at this point. Place the functions into a vector and use
666// atexit() as soon as it is ready for use (i.e. after .CRT$XIC initializers).
667InternalMmapVectorNoCtor<void (*)(void)> atexit_functions;
668
669int Atexit(void (*function)(void)) {
670 atexit_functions.push_back(function);
671 return 0;
672}
673
674static int RunAtexit() {
675 TraceLoggingUnregister(g_asan_provider);
676 int ret = 0;
677 for (uptr i = 0; i < atexit_functions.size(); ++i) {
678 ret |= atexit(atexit_functions[i]);
679 }
680 return ret;
681}
682
683#pragma section(".CRT$XID", long, read)
684__declspec(allocate(".CRT$XID")) int (*__run_atexit)() = RunAtexit;
685#endif
686
687// ------------------ sanitizer_libc.h
688fd_t OpenFile(const char *filename, FileAccessMode mode, error_t *last_error) {
689 // FIXME: Use the wide variants to handle Unicode filenames.
690 fd_t res;
691 if (mode == RdOnly) {
692 res = CreateFileA(filename, GENERIC_READ,
693 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
694 nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
695 } else if (mode == WrOnly) {
696 res = CreateFileA(filename, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS,
697 FILE_ATTRIBUTE_NORMAL, nullptr);
698 } else {
699 UNIMPLEMENTED();
700 }
701 CHECK(res != kStdoutFd || kStdoutFd == kInvalidFd);
702 CHECK(res != kStderrFd || kStderrFd == kInvalidFd);
703 if (res == kInvalidFd && last_error)
704 *last_error = GetLastError();
705 return res;
706}
707
708void CloseFile(fd_t fd) {
709 CloseHandle(fd);
710}
711
712bool ReadFromFile(fd_t fd, void *buff, uptr buff_size, uptr *bytes_read,
713 error_t *error_p) {
714 CHECK(fd != kInvalidFd);
715
716 // bytes_read can't be passed directly to ReadFile:
717 // uptr is unsigned long long on 64-bit Windows.
718 unsigned long num_read_long;
719
720 bool success = ::ReadFile(fd, buff, buff_size, &num_read_long, nullptr);
721 if (!success && error_p)
722 *error_p = GetLastError();
723 if (bytes_read)
724 *bytes_read = num_read_long;
725 return success;
726}
727
728bool SupportsColoredOutput(fd_t fd) {
729 // FIXME: support colored output.
730 return false;
731}
732
733bool WriteToFile(fd_t fd, const void *buff, uptr buff_size, uptr *bytes_written,
734 error_t *error_p) {
735 CHECK(fd != kInvalidFd);
736
737 // Handle null optional parameters.
738 error_t dummy_error;
739 error_p = error_p ? error_p : &dummy_error;
740 uptr dummy_bytes_written;
741 bytes_written = bytes_written ? bytes_written : &dummy_bytes_written;
742
743 // Initialize output parameters in case we fail.
744 *error_p = 0;
745 *bytes_written = 0;
746
747 // Map the conventional Unix fds 1 and 2 to Windows handles. They might be
748 // closed, in which case this will fail.
749 if (fd == kStdoutFd || fd == kStderrFd) {
750 fd = GetStdHandle(fd == kStdoutFd ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE);
751 if (fd == 0) {
752 *error_p = ERROR_INVALID_HANDLE;
753 return false;
754 }
755 }
756
757 DWORD bytes_written_32;
758 if (!WriteFile(fd, buff, buff_size, &bytes_written_32, 0)) {
759 *error_p = GetLastError();
760 return false;
761 } else {
762 *bytes_written = bytes_written_32;
763 return true;
764 }
765}
766
767uptr internal_sched_yield() {
768 Sleep(0);
769 return 0;
770}
771
772void internal__exit(int exitcode) {
773 TraceLoggingUnregister(g_asan_provider);
774 // ExitProcess runs some finalizers, so use TerminateProcess to avoid that.
775 // The debugger doesn't stop on TerminateProcess like it does on ExitProcess,
776 // so add our own breakpoint here.
777 if (::IsDebuggerPresent())
778 __debugbreak();
779 TerminateProcess(GetCurrentProcess(), exitcode);
780 BUILTIN_UNREACHABLE();
781}
782
783uptr internal_ftruncate(fd_t fd, uptr size) {
784 UNIMPLEMENTED();
785}
786
787uptr GetRSS() {
788 PROCESS_MEMORY_COUNTERS counters;
789 if (!GetProcessMemoryInfo(GetCurrentProcess(), &counters, sizeof(counters)))
790 return 0;
791 return counters.WorkingSetSize;
792}
793
794void *internal_start_thread(void *(*func)(void *arg), void *arg) { return 0; }
795void internal_join_thread(void *th) { }
796
797// ---------------------- BlockingMutex ---------------- {{{1
798
799BlockingMutex::BlockingMutex() {
800 CHECK(sizeof(SRWLOCK) <= sizeof(opaque_storage_));
801 internal_memset(this, 0, sizeof(*this));
802}
803
804void BlockingMutex::Lock() {
805 AcquireSRWLockExclusive((PSRWLOCK)opaque_storage_);
806 CHECK_EQ(owner_, 0);
807 owner_ = GetThreadSelf();
808}
809
810void BlockingMutex::Unlock() {
811 CheckLocked();
812 owner_ = 0;
813 ReleaseSRWLockExclusive((PSRWLOCK)opaque_storage_);
814}
815
816void BlockingMutex::CheckLocked() {
817 CHECK_EQ(owner_, GetThreadSelf());
818}
819
820uptr GetTlsSize() {
821 return 0;
822}
823
824void InitTlsSize() {
825}
826
827void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
828 uptr *tls_addr, uptr *tls_size) {
829#if SANITIZER_GO
830 *stk_addr = 0;
831 *stk_size = 0;
832 *tls_addr = 0;
833 *tls_size = 0;
834#else
835 uptr stack_top, stack_bottom;
836 GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
837 *stk_addr = stack_bottom;
838 *stk_size = stack_top - stack_bottom;
839 *tls_addr = 0;
840 *tls_size = 0;
841#endif
842}
843
844void ReportFile::Write(const char *buffer, uptr length) {
845 SpinMutexLock l(mu);
846 ReopenIfNecessary();
847 if (!WriteToFile(fd, buffer, length)) {
848 // stderr may be closed, but we may be able to print to the debugger
849 // instead. This is the case when launching a program from Visual Studio,
850 // and the following routine should write to its console.
851 OutputDebugStringA(buffer);
852 }
853}
854
855void SetAlternateSignalStack() {
856 // FIXME: Decide what to do on Windows.
857}
858
859void UnsetAlternateSignalStack() {
860 // FIXME: Decide what to do on Windows.
861}
862
863void InstallDeadlySignalHandlers(SignalHandlerType handler) {
864 (void)handler;
865 // FIXME: Decide what to do on Windows.
866}
867
868HandleSignalMode GetHandleSignalMode(int signum) {
869 // FIXME: Decide what to do on Windows.
870 return kHandleSignalNo;
871}
872
873// Check based on flags if we should handle this exception.
874bool IsHandledDeadlyException(DWORD exceptionCode) {
875 switch (exceptionCode) {
876 case EXCEPTION_ACCESS_VIOLATION:
877 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
878 case EXCEPTION_STACK_OVERFLOW:
879 case EXCEPTION_DATATYPE_MISALIGNMENT:
880 case EXCEPTION_IN_PAGE_ERROR:
881 return common_flags()->handle_segv;
882 case EXCEPTION_ILLEGAL_INSTRUCTION:
883 case EXCEPTION_PRIV_INSTRUCTION:
884 case EXCEPTION_BREAKPOINT:
885 return common_flags()->handle_sigill;
886 case EXCEPTION_FLT_DENORMAL_OPERAND:
887 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
888 case EXCEPTION_FLT_INEXACT_RESULT:
889 case EXCEPTION_FLT_INVALID_OPERATION:
890 case EXCEPTION_FLT_OVERFLOW:
891 case EXCEPTION_FLT_STACK_CHECK:
892 case EXCEPTION_FLT_UNDERFLOW:
893 case EXCEPTION_INT_DIVIDE_BY_ZERO:
894 case EXCEPTION_INT_OVERFLOW:
895 return common_flags()->handle_sigfpe;
896 }
897 return false;
898}
899
900bool IsAccessibleMemoryRange(uptr beg, uptr size) {
901 SYSTEM_INFO si;
902 GetNativeSystemInfo(&si);
903 uptr page_size = si.dwPageSize;
904 uptr page_mask = ~(page_size - 1);
905
906 for (uptr page = beg & page_mask, end = (beg + size - 1) & page_mask;
907 page <= end;) {
908 MEMORY_BASIC_INFORMATION info;
909 if (VirtualQuery((LPCVOID)page, &info, sizeof(info)) != sizeof(info))
910 return false;
911
912 if (info.Protect == 0 || info.Protect == PAGE_NOACCESS ||
913 info.Protect == PAGE_EXECUTE)
914 return false;
915
916 if (info.RegionSize == 0)
917 return false;
918
919 page += info.RegionSize;
920 }
921
922 return true;
923}
924
925bool SignalContext::IsStackOverflow() const {
926 return (DWORD)GetType() == EXCEPTION_STACK_OVERFLOW;
927}
928
929void SignalContext::InitPcSpBp() {
930 EXCEPTION_RECORD *exception_record = (EXCEPTION_RECORD *)siginfo;
931 CONTEXT *context_record = (CONTEXT *)context;
932
933 pc = (uptr)exception_record->ExceptionAddress;
934#ifdef _WIN64
935 bp = (uptr)context_record->Rbp;
936 sp = (uptr)context_record->Rsp;
937#else
938 bp = (uptr)context_record->Ebp;
939 sp = (uptr)context_record->Esp;
940#endif
941}
942
943uptr SignalContext::GetAddress() const {
944 EXCEPTION_RECORD *exception_record = (EXCEPTION_RECORD *)siginfo;
945 return exception_record->ExceptionInformation[1];
946}
947
948bool SignalContext::IsMemoryAccess() const {
949 return GetWriteFlag() != SignalContext::UNKNOWN;
950}
951
952bool SignalContext::IsTrueFaultingAddress() const {
953 // FIXME: Provide real implementation for this. See Linux and Mac variants.
954 return IsMemoryAccess();
955}
956
957SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
958 EXCEPTION_RECORD *exception_record = (EXCEPTION_RECORD *)siginfo;
959 // The contents of this array are documented at
960 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa363082(v=vs.85).aspx
961 // The first element indicates read as 0, write as 1, or execute as 8. The
962 // second element is the faulting address.
963 switch (exception_record->ExceptionInformation[0]) {
964 case 0:
965 return SignalContext::READ;
966 case 1:
967 return SignalContext::WRITE;
968 case 8:
969 return SignalContext::UNKNOWN;
970 }
971 return SignalContext::UNKNOWN;
972}
973
974void SignalContext::DumpAllRegisters(void *context) {
975 // FIXME: Implement this.
976}
977
978int SignalContext::GetType() const {
979 return static_cast<const EXCEPTION_RECORD *>(siginfo)->ExceptionCode;
980}
981
982const char *SignalContext::Describe() const {
983 unsigned code = GetType();
984 // Get the string description of the exception if this is a known deadly
985 // exception.
986 switch (code) {
987 case EXCEPTION_ACCESS_VIOLATION:
988 return "access-violation";
989 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
990 return "array-bounds-exceeded";
991 case EXCEPTION_STACK_OVERFLOW:
992 return "stack-overflow";
993 case EXCEPTION_DATATYPE_MISALIGNMENT:
994 return "datatype-misalignment";
995 case EXCEPTION_IN_PAGE_ERROR:
996 return "in-page-error";
997 case EXCEPTION_ILLEGAL_INSTRUCTION:
998 return "illegal-instruction";
999 case EXCEPTION_PRIV_INSTRUCTION:
1000 return "priv-instruction";
1001 case EXCEPTION_BREAKPOINT:
1002 return "breakpoint";
1003 case EXCEPTION_FLT_DENORMAL_OPERAND:
1004 return "flt-denormal-operand";
1005 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
1006 return "flt-divide-by-zero";
1007 case EXCEPTION_FLT_INEXACT_RESULT:
1008 return "flt-inexact-result";
1009 case EXCEPTION_FLT_INVALID_OPERATION:
1010 return "flt-invalid-operation";
1011 case EXCEPTION_FLT_OVERFLOW:
1012 return "flt-overflow";
1013 case EXCEPTION_FLT_STACK_CHECK:
1014 return "flt-stack-check";
1015 case EXCEPTION_FLT_UNDERFLOW:
1016 return "flt-underflow";
1017 case EXCEPTION_INT_DIVIDE_BY_ZERO:
1018 return "int-divide-by-zero";
1019 case EXCEPTION_INT_OVERFLOW:
1020 return "int-overflow";
1021 }
1022 return "unknown exception";
1023}
1024
1025uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
1026 // FIXME: Actually implement this function.
1027 CHECK_GT(buf_len, 0);
1028 buf[0] = 0;
1029 return 0;
1030}
1031
1032uptr ReadLongProcessName(/*out*/char *buf, uptr buf_len) {
1033 return ReadBinaryName(buf, buf_len);
1034}
1035
1036void CheckVMASize() {
1037 // Do nothing.
1038}
1039
1040void InitializePlatformEarly() {
1041 // Do nothing.
1042}
1043
1044void MaybeReexec() {
1045 // No need to re-exec on Windows.
1046}
1047
1048void CheckASLR() {
1049 // Do nothing
1050}
1051
1052void CheckMPROTECT() {
1053 // Do nothing
1054}
1055
1056char **GetArgv() {
1057 // FIXME: Actually implement this function.
1058 return 0;
1059}
1060
1061char **GetEnviron() {
1062 // FIXME: Actually implement this function.
1063 return 0;
1064}
1065
1066pid_t StartSubprocess(const char *program, const char *const argv[],
1067 const char *const envp[], fd_t stdin_fd, fd_t stdout_fd,
1068 fd_t stderr_fd) {
1069 // FIXME: implement on this platform
1070 // Should be implemented based on
1071 // SymbolizerProcess::StarAtSymbolizerSubprocess
1072 // from lib/sanitizer_common/sanitizer_symbolizer_win.cpp.
1073 return -1;
1074}
1075
1076bool IsProcessRunning(pid_t pid) {
1077 // FIXME: implement on this platform.
1078 return false;
1079}
1080
1081int WaitForProcess(pid_t pid) { return -1; }
1082
1083// FIXME implement on this platform.
1084void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size) { }
1085
1086void CheckNoDeepBind(const char *filename, int flag) {
1087 // Do nothing.
1088}
1089
1090// FIXME: implement on this platform.
1091bool GetRandom(void *buffer, uptr length, bool blocking) {
1092 UNIMPLEMENTED();
1093}
1094
1095u32 GetNumberOfCPUs() {
1096 SYSTEM_INFO sysinfo = {};
1097 GetNativeSystemInfo(&sysinfo);
1098 return sysinfo.dwNumberOfProcessors;
1099}
1100
1101#if SANITIZER_WIN_TRACE
1102// TODO(mcgov): Rename this project-wide to PlatformLogInit
1103void AndroidLogInit(void) {
1104 HRESULT hr = TraceLoggingRegister(g_asan_provider);
1105 if (!SUCCEEDED(hr))
1106 return;
1107}
1108
1109void SetAbortMessage(const char *) {}
1110
1111void LogFullErrorReport(const char *buffer) {
1112 if (common_flags()->log_to_syslog) {
1113 InternalMmapVector<wchar_t> filename;
1114 DWORD filename_length = 0;
1115 do {
1116 filename.resize(filename.size() + 0x100);
1117 filename_length =
1118 GetModuleFileNameW(NULL, filename.begin(), filename.size());
1119 } while (filename_length >= filename.size());
1120 TraceLoggingWrite(g_asan_provider, "AsanReportEvent",
1121 TraceLoggingValue(filename.begin(), "ExecutableName"),
1122 TraceLoggingValue(buffer, "AsanReportContents"));
1123 }
1124}
1125#endif // SANITIZER_WIN_TRACE
1126
1127} // namespace __sanitizer
1128
1129#endif // _WIN32
lib/tsan/sanitizer_common/sanitizer_win.h created+25
...@@ -0,0 +1,25 @@
1//===-- sanitizer_win.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// Windows-specific declarations.
10//
11//===----------------------------------------------------------------------===//
12#ifndef SANITIZER_WIN_H
13#define SANITIZER_WIN_H
14
15#include "sanitizer_platform.h"
16#if SANITIZER_WINDOWS
17#include "sanitizer_internal_defs.h"
18
19namespace __sanitizer {
20// Check based on flags if we should handle the exception.
21bool IsHandledDeadlyException(DWORD exceptionCode);
22} // namespace __sanitizer
23
24#endif // SANITIZER_WINDOWS
25#endif // SANITIZER_WIN_H
lib/tsan/sanitizer_common/sanitizer_win_defs.h created+174
...@@ -0,0 +1,174 @@
1//===-- sanitizer_win_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// Common definitions for Windows-specific code.
10//
11//===----------------------------------------------------------------------===//
12#ifndef SANITIZER_WIN_DEFS_H
13#define SANITIZER_WIN_DEFS_H
14
15#include "sanitizer_platform.h"
16#if SANITIZER_WINDOWS
17
18#ifndef WINAPI
19#if defined(_M_IX86) || defined(__i386__)
20#define WINAPI __stdcall
21#else
22#define WINAPI
23#endif
24#endif
25
26#if defined(_M_IX86) || defined(__i386__)
27#define WIN_SYM_PREFIX "_"
28#else
29#define WIN_SYM_PREFIX
30#endif
31
32// For MinGW, the /export: directives contain undecorated symbols, contrary to
33// link/lld-link. The GNU linker doesn't support /alternatename and /include
34// though, thus lld-link in MinGW mode interprets them in the same way as
35// in the default mode.
36#ifdef __MINGW32__
37#define WIN_EXPORT_PREFIX
38#else
39#define WIN_EXPORT_PREFIX WIN_SYM_PREFIX
40#endif
41
42// Intermediate macro to ensure the parameter is expanded before stringified.
43#define STRINGIFY_(A) #A
44#define STRINGIFY(A) STRINGIFY_(A)
45
46#if !SANITIZER_GO
47
48// ----------------- A workaround for the absence of weak symbols --------------
49// We don't have a direct equivalent of weak symbols when using MSVC, but we can
50// use the /alternatename directive to tell the linker to default a specific
51// symbol to a specific value.
52// Take into account that this is a pragma directive for the linker, so it will
53// be ignored by the compiler and the function will be marked as UNDEF in the
54// symbol table of the resulting object file. The linker won't find the default
55// implementation until it links with that object file.
56// So, suppose we provide a default implementation "fundef" for "fun", and this
57// is compiled into the object file "test.obj" including the pragma directive.
58// If we have some code with references to "fun" and we link that code with
59// "test.obj", it will work because the linker always link object files.
60// But, if "test.obj" is included in a static library, like "test.lib", then the
61// liker will only link to "test.obj" if necessary. If we only included the
62// definition of "fun", it won't link to "test.obj" (from test.lib) because
63// "fun" appears as UNDEF, so it doesn't resolve the symbol "fun", and will
64// result in a link error (the linker doesn't find the pragma directive).
65// So, a workaround is to force linkage with the modules that include weak
66// definitions, with the following macro: WIN_FORCE_LINK()
67
68#define WIN_WEAK_ALIAS(Name, Default) \
69 __pragma(comment(linker, "/alternatename:" WIN_SYM_PREFIX STRINGIFY(Name) "="\
70 WIN_SYM_PREFIX STRINGIFY(Default)))
71
72#define WIN_FORCE_LINK(Name) \
73 __pragma(comment(linker, "/include:" WIN_SYM_PREFIX STRINGIFY(Name)))
74
75#define WIN_EXPORT(ExportedName, Name) \
76 __pragma(comment(linker, "/export:" WIN_EXPORT_PREFIX STRINGIFY(ExportedName)\
77 "=" WIN_EXPORT_PREFIX STRINGIFY(Name)))
78
79// We cannot define weak functions on Windows, but we can use WIN_WEAK_ALIAS()
80// which defines an alias to a default implementation, and only works when
81// linking statically.
82// So, to define a weak function "fun", we define a default implementation with
83// a different name "fun__def" and we create a "weak alias" fun = fun__def.
84// Then, users can override it just defining "fun".
85// We impose "extern "C"" because otherwise WIN_WEAK_ALIAS() will fail because
86// of name mangling.
87
88// Dummy name for default implementation of weak function.
89# define WEAK_DEFAULT_NAME(Name) Name##__def
90// Name for exported implementation of weak function.
91# define WEAK_EXPORT_NAME(Name) Name##__dll
92
93// Use this macro when you need to define and export a weak function from a
94// library. For example:
95// WIN_WEAK_EXPORT_DEF(bool, compare, int a, int b) { return a > b; }
96# define WIN_WEAK_EXPORT_DEF(ReturnType, Name, ...) \
97 WIN_WEAK_ALIAS(Name, WEAK_DEFAULT_NAME(Name)) \
98 WIN_EXPORT(WEAK_EXPORT_NAME(Name), Name) \
99 extern "C" ReturnType Name(__VA_ARGS__); \
100 extern "C" ReturnType WEAK_DEFAULT_NAME(Name)(__VA_ARGS__)
101
102// Use this macro when you need to import a weak function from a library. It
103// defines a weak alias to the imported function from the dll. For example:
104// WIN_WEAK_IMPORT_DEF(compare)
105# define WIN_WEAK_IMPORT_DEF(Name) \
106 WIN_WEAK_ALIAS(Name, WEAK_EXPORT_NAME(Name))
107
108// So, for Windows we provide something similar to weak symbols in Linux, with
109// some differences:
110// + A default implementation must always be provided.
111//
112// + When linking statically it works quite similarly. For example:
113//
114// // libExample.cc
115// WIN_WEAK_EXPORT_DEF(bool, compare, int a, int b) { return a > b; }
116//
117// // client.cc
118// // We can use the default implementation from the library:
119// compare(1, 2);
120// // Or we can override it:
121// extern "C" bool compare (int a, int b) { return a >= b; }
122//
123// And it will work fine. If we don't override the function, we need to ensure
124// that the linker includes the object file with the default implementation.
125// We can do so with the linker option "-wholearchive:".
126//
127// + When linking dynamically with a library (dll), weak functions are exported
128// with "__dll" suffix. Clients can use the macro WIN_WEAK_IMPORT_DEF(fun)
129// which defines a "weak alias" fun = fun__dll.
130//
131// // libExample.cc
132// WIN_WEAK_EXPORT_DEF(bool, compare, int a, int b) { return a > b; }
133//
134// // client.cc
135// WIN_WEAK_IMPORT_DEF(compare)
136// // We can use the default implementation from the library:
137// compare(1, 2);
138// // Or we can override it:
139// extern "C" bool compare (int a, int b) { return a >= b; }
140//
141// But if we override the function, the dlls don't have access to it (which
142// is different in linux). If that is desired, the strong definition must be
143// exported and interception can be used from the rest of the dlls.
144//
145// // libExample.cc
146// WIN_WEAK_EXPORT_DEF(bool, compare, int a, int b) { return a > b; }
147// // When initialized, check if the main executable defined "compare".
148// int libExample_init() {
149// uptr fnptr = __interception::InternalGetProcAddress(
150// (void *)GetModuleHandleA(0), "compare");
151// if (fnptr && !__interception::OverrideFunction((uptr)compare, fnptr, 0))
152// abort();
153// return 0;
154// }
155//
156// // client.cc
157// WIN_WEAK_IMPORT_DEF(compare)
158// // We override and export compare:
159// extern "C" __declspec(dllexport) bool compare (int a, int b) {
160// return a >= b;
161// }
162//
163
164#else // SANITIZER_GO
165
166// Go neither needs nor wants weak references.
167// The shenanigans above don't work for gcc.
168# define WIN_WEAK_EXPORT_DEF(ReturnType, Name, ...) \
169 extern "C" ReturnType Name(__VA_ARGS__)
170
171#endif // SANITIZER_GO
172
173#endif // SANITIZER_WINDOWS
174#endif // SANITIZER_WIN_DEFS_H
lib/tsan/sanitizer_common/sanitizer_win_dll_thunk.h created+181
...@@ -0,0 +1,181 @@
1//===-- sanitizer_win_dll_thunk.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// This header provide helper macros to delegate calls to the shared runtime
9// that lives in the main executable. It should be included to dll_thunks that
10// will be linked to the dlls, when the sanitizer is a static library included
11// in the main executable.
12//===----------------------------------------------------------------------===//
13#ifndef SANITIZER_WIN_DLL_THUNK_H
14#define SANITIZER_WIN_DLL_THUNK_H
15#include "sanitizer_internal_defs.h"
16
17namespace __sanitizer {
18uptr dllThunkGetRealAddrOrDie(const char *name);
19
20int dllThunkIntercept(const char* main_function, uptr dll_function);
21
22int dllThunkInterceptWhenPossible(const char* main_function,
23 const char* default_function, uptr dll_function);
24}
25
26extern "C" int __dll_thunk_init();
27
28// ----------------- Function interception helper macros -------------------- //
29// Override dll_function with main_function from main executable.
30#define INTERCEPT_OR_DIE(main_function, dll_function) \
31 static int intercept_##dll_function() { \
32 return __sanitizer::dllThunkIntercept(main_function, (__sanitizer::uptr) \
33 dll_function); \
34 } \
35 __pragma(section(".DLLTH$M", long, read)) \
36 __declspec(allocate(".DLLTH$M")) int (*__dll_thunk_##dll_function)() = \
37 intercept_##dll_function;
38
39// Try to override dll_function with main_function from main executable.
40// If main_function is not present, override dll_function with default_function.
41#define INTERCEPT_WHEN_POSSIBLE(main_function, default_function, dll_function) \
42 static int intercept_##dll_function() { \
43 return __sanitizer::dllThunkInterceptWhenPossible(main_function, \
44 default_function, (__sanitizer::uptr)dll_function); \
45 } \
46 __pragma(section(".DLLTH$M", long, read)) \
47 __declspec(allocate(".DLLTH$M")) int (*__dll_thunk_##dll_function)() = \
48 intercept_##dll_function;
49
50// -------------------- Function interception macros ------------------------ //
51// Special case of hooks -- ASan own interface functions. Those are only called
52// after __asan_init, thus an empty implementation is sufficient.
53#define INTERCEPT_SANITIZER_FUNCTION(name) \
54 extern "C" __declspec(noinline) void name() { \
55 volatile int prevent_icf = (__LINE__ << 8) ^ __COUNTER__; \
56 static const char function_name[] = #name; \
57 for (const char* ptr = &function_name[0]; *ptr; ++ptr) \
58 prevent_icf ^= *ptr; \
59 (void)prevent_icf; \
60 __debugbreak(); \
61 } \
62 INTERCEPT_OR_DIE(#name, name)
63
64// Special case of hooks -- Weak functions, could be redefined in the main
65// executable, but that is not necessary, so we shouldn't die if we can not find
66// a reference. Instead, when the function is not present in the main executable
67// we consider the default impl provided by asan library.
68#define INTERCEPT_SANITIZER_WEAK_FUNCTION(name) \
69 extern "C" __declspec(noinline) void name() { \
70 volatile int prevent_icf = (__LINE__ << 8) ^ __COUNTER__; \
71 static const char function_name[] = #name; \
72 for (const char* ptr = &function_name[0]; *ptr; ++ptr) \
73 prevent_icf ^= *ptr; \
74 (void)prevent_icf; \
75 __debugbreak(); \
76 } \
77 INTERCEPT_WHEN_POSSIBLE(#name, STRINGIFY(WEAK_EXPORT_NAME(name)), name)
78
79// We can't define our own version of strlen etc. because that would lead to
80// link-time or even type mismatch errors. Instead, we can declare a function
81// just to be able to get its address. Me may miss the first few calls to the
82// functions since it can be called before __dll_thunk_init, but that would lead
83// to false negatives in the startup code before user's global initializers,
84// which isn't a big deal.
85#define INTERCEPT_LIBRARY_FUNCTION(name) \
86 extern "C" void name(); \
87 INTERCEPT_OR_DIE(WRAPPER_NAME(name), name)
88
89// Use these macros for functions that could be called before __dll_thunk_init()
90// is executed and don't lead to errors if defined (free, malloc, etc).
91#define INTERCEPT_WRAP_V_V(name) \
92 extern "C" void name() { \
93 typedef decltype(name) *fntype; \
94 static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \
95 fn(); \
96 } \
97 INTERCEPT_OR_DIE(#name, name);
98
99#define INTERCEPT_WRAP_V_W(name) \
100 extern "C" void name(void *arg) { \
101 typedef decltype(name) *fntype; \
102 static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \
103 fn(arg); \
104 } \
105 INTERCEPT_OR_DIE(#name, name);
106
107#define INTERCEPT_WRAP_V_WW(name) \
108 extern "C" void name(void *arg1, void *arg2) { \
109 typedef decltype(name) *fntype; \
110 static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \
111 fn(arg1, arg2); \
112 } \
113 INTERCEPT_OR_DIE(#name, name);
114
115#define INTERCEPT_WRAP_V_WWW(name) \
116 extern "C" void name(void *arg1, void *arg2, void *arg3) { \
117 typedef decltype(name) *fntype; \
118 static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \
119 fn(arg1, arg2, arg3); \
120 } \
121 INTERCEPT_OR_DIE(#name, name);
122
123#define INTERCEPT_WRAP_W_V(name) \
124 extern "C" void *name() { \
125 typedef decltype(name) *fntype; \
126 static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \
127 return fn(); \
128 } \
129 INTERCEPT_OR_DIE(#name, name);
130
131#define INTERCEPT_WRAP_W_W(name) \
132 extern "C" void *name(void *arg) { \
133 typedef decltype(name) *fntype; \
134 static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \
135 return fn(arg); \
136 } \
137 INTERCEPT_OR_DIE(#name, name);
138
139#define INTERCEPT_WRAP_W_WW(name) \
140 extern "C" void *name(void *arg1, void *arg2) { \
141 typedef decltype(name) *fntype; \
142 static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \
143 return fn(arg1, arg2); \
144 } \
145 INTERCEPT_OR_DIE(#name, name);
146
147#define INTERCEPT_WRAP_W_WWW(name) \
148 extern "C" void *name(void *arg1, void *arg2, void *arg3) { \
149 typedef decltype(name) *fntype; \
150 static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \
151 return fn(arg1, arg2, arg3); \
152 } \
153 INTERCEPT_OR_DIE(#name, name);
154
155#define INTERCEPT_WRAP_W_WWWW(name) \
156 extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4) { \
157 typedef decltype(name) *fntype; \
158 static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \
159 return fn(arg1, arg2, arg3, arg4); \
160 } \
161 INTERCEPT_OR_DIE(#name, name);
162
163#define INTERCEPT_WRAP_W_WWWWW(name) \
164 extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4, \
165 void *arg5) { \
166 typedef decltype(name) *fntype; \
167 static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \
168 return fn(arg1, arg2, arg3, arg4, arg5); \
169 } \
170 INTERCEPT_OR_DIE(#name, name);
171
172#define INTERCEPT_WRAP_W_WWWWWW(name) \
173 extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4, \
174 void *arg5, void *arg6) { \
175 typedef decltype(name) *fntype; \
176 static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \
177 return fn(arg1, arg2, arg3, arg4, arg5, arg6); \
178 } \
179 INTERCEPT_OR_DIE(#name, name);
180
181#endif // SANITIZER_WIN_DLL_THUNK_H
lib/tsan/sanitizer_common/sanitizer_win_weak_interception.h created+32
...@@ -0,0 +1,32 @@
1//===-- sanitizer_win_weak_interception.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// This header provide helper macros to delegate calls of weak functions to the
9// implementation in the main executable when a strong definition is present.
10//===----------------------------------------------------------------------===//
11#ifndef SANITIZER_WIN_WEAK_INTERCEPTION_H
12#define SANITIZER_WIN_WEAK_INTERCEPTION_H
13#include "sanitizer_internal_defs.h"
14
15namespace __sanitizer {
16int interceptWhenPossible(uptr dll_function, const char *real_function);
17}
18
19// ----------------- Function interception helper macros -------------------- //
20// Weak functions, could be redefined in the main executable, but that is not
21// necessary, so we shouldn't die if we can not find a reference.
22#define INTERCEPT_WEAK(Name) interceptWhenPossible((uptr) Name, #Name);
23
24#define INTERCEPT_SANITIZER_WEAK_FUNCTION(Name) \
25 static int intercept_##Name() { \
26 return __sanitizer::interceptWhenPossible((__sanitizer::uptr) Name, #Name);\
27 } \
28 __pragma(section(".WEAK$M", long, read)) \
29 __declspec(allocate(".WEAK$M")) int (*__weak_intercept_##Name)() = \
30 intercept_##Name;
31
32#endif // SANITIZER_WIN_WEAK_INTERCEPTION_H
lib/tsan/tsan_clock.cpp created+655
...@@ -0,0 +1,655 @@
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
83// We don't have ThreadState in these methods, so this is an ugly hack that
84// works only in C++.
85#if !SANITIZER_GO
86# define CPP_STAT_INC(typ) StatInc(cur_thread(), typ)
87#else
88# define CPP_STAT_INC(typ) (void)0
89#endif
90
91namespace __tsan {
92
93static atomic_uint32_t *ref_ptr(ClockBlock *cb) {
94 return reinterpret_cast<atomic_uint32_t *>(&cb->table[ClockBlock::kRefIdx]);
95}
96
97// Drop reference to the first level block idx.
98static void UnrefClockBlock(ClockCache *c, u32 idx, uptr blocks) {
99 ClockBlock *cb = ctx->clock_alloc.Map(idx);
100 atomic_uint32_t *ref = ref_ptr(cb);
101 u32 v = atomic_load(ref, memory_order_acquire);
102 for (;;) {
103 CHECK_GT(v, 0);
104 if (v == 1)
105 break;
106 if (atomic_compare_exchange_strong(ref, &v, v - 1, memory_order_acq_rel))
107 return;
108 }
109 // First level block owns second level blocks, so them as well.
110 for (uptr i = 0; i < blocks; i++)
111 ctx->clock_alloc.Free(c, cb->table[ClockBlock::kBlockIdx - i]);
112 ctx->clock_alloc.Free(c, idx);
113}
114
115ThreadClock::ThreadClock(unsigned tid, unsigned reused)
116 : tid_(tid)
117 , reused_(reused + 1) // 0 has special meaning
118 , last_acquire_()
119 , global_acquire_()
120 , cached_idx_()
121 , cached_size_()
122 , cached_blocks_() {
123 CHECK_LT(tid, kMaxTidInClock);
124 CHECK_EQ(reused_, ((u64)reused_ << kClkBits) >> kClkBits);
125 nclk_ = tid_ + 1;
126 internal_memset(clk_, 0, sizeof(clk_));
127}
128
129void ThreadClock::ResetCached(ClockCache *c) {
130 if (cached_idx_) {
131 UnrefClockBlock(c, cached_idx_, cached_blocks_);
132 cached_idx_ = 0;
133 cached_size_ = 0;
134 cached_blocks_ = 0;
135 }
136}
137
138void ThreadClock::acquire(ClockCache *c, SyncClock *src) {
139 DCHECK_LE(nclk_, kMaxTid);
140 DCHECK_LE(src->size_, kMaxTid);
141 CPP_STAT_INC(StatClockAcquire);
142
143 // Check if it's empty -> no need to do anything.
144 const uptr nclk = src->size_;
145 if (nclk == 0) {
146 CPP_STAT_INC(StatClockAcquireEmpty);
147 return;
148 }
149
150 bool acquired = false;
151 for (unsigned i = 0; i < kDirtyTids; i++) {
152 SyncClock::Dirty dirty = src->dirty_[i];
153 unsigned tid = dirty.tid;
154 if (tid != kInvalidTid) {
155 if (clk_[tid] < dirty.epoch) {
156 clk_[tid] = dirty.epoch;
157 acquired = true;
158 }
159 }
160 }
161
162 // Check if we've already acquired src after the last release operation on src
163 if (tid_ >= nclk || src->elem(tid_).reused != reused_) {
164 // O(N) acquire.
165 CPP_STAT_INC(StatClockAcquireFull);
166 nclk_ = max(nclk_, nclk);
167 u64 *dst_pos = &clk_[0];
168 for (ClockElem &src_elem : *src) {
169 u64 epoch = src_elem.epoch;
170 if (*dst_pos < epoch) {
171 *dst_pos = epoch;
172 acquired = true;
173 }
174 dst_pos++;
175 }
176
177 // Remember that this thread has acquired this clock.
178 if (nclk > tid_)
179 src->elem(tid_).reused = reused_;
180 }
181
182 if (acquired) {
183 CPP_STAT_INC(StatClockAcquiredSomething);
184 last_acquire_ = clk_[tid_];
185 ResetCached(c);
186 }
187}
188
189void ThreadClock::releaseStoreAcquire(ClockCache *c, SyncClock *sc) {
190 DCHECK_LE(nclk_, kMaxTid);
191 DCHECK_LE(sc->size_, kMaxTid);
192
193 if (sc->size_ == 0) {
194 // ReleaseStore will correctly set release_store_tid_,
195 // which can be important for future operations.
196 ReleaseStore(c, sc);
197 return;
198 }
199
200 nclk_ = max(nclk_, (uptr) sc->size_);
201
202 // Check if we need to resize sc.
203 if (sc->size_ < nclk_)
204 sc->Resize(c, nclk_);
205
206 bool acquired = false;
207
208 sc->Unshare(c);
209 // Update sc->clk_.
210 sc->FlushDirty();
211 uptr i = 0;
212 for (ClockElem &ce : *sc) {
213 u64 tmp = clk_[i];
214 if (clk_[i] < ce.epoch) {
215 clk_[i] = ce.epoch;
216 acquired = true;
217 }
218 ce.epoch = tmp;
219 ce.reused = 0;
220 i++;
221 }
222 sc->release_store_tid_ = kInvalidTid;
223 sc->release_store_reused_ = 0;
224
225 if (acquired) {
226 CPP_STAT_INC(StatClockAcquiredSomething);
227 last_acquire_ = clk_[tid_];
228 ResetCached(c);
229 }
230}
231
232void ThreadClock::release(ClockCache *c, SyncClock *dst) {
233 DCHECK_LE(nclk_, kMaxTid);
234 DCHECK_LE(dst->size_, kMaxTid);
235
236 if (dst->size_ == 0) {
237 // ReleaseStore will correctly set release_store_tid_,
238 // which can be important for future operations.
239 ReleaseStore(c, dst);
240 return;
241 }
242
243 CPP_STAT_INC(StatClockRelease);
244 // Check if we need to resize dst.
245 if (dst->size_ < nclk_)
246 dst->Resize(c, nclk_);
247
248 // Check if we had not acquired anything from other threads
249 // since the last release on dst. If so, we need to update
250 // only dst->elem(tid_).
251 if (!HasAcquiredAfterRelease(dst)) {
252 UpdateCurrentThread(c, dst);
253 if (dst->release_store_tid_ != tid_ ||
254 dst->release_store_reused_ != reused_)
255 dst->release_store_tid_ = kInvalidTid;
256 return;
257 }
258
259 // O(N) release.
260 CPP_STAT_INC(StatClockReleaseFull);
261 dst->Unshare(c);
262 // First, remember whether we've acquired dst.
263 bool acquired = IsAlreadyAcquired(dst);
264 if (acquired)
265 CPP_STAT_INC(StatClockReleaseAcquired);
266 // Update dst->clk_.
267 dst->FlushDirty();
268 uptr i = 0;
269 for (ClockElem &ce : *dst) {
270 ce.epoch = max(ce.epoch, clk_[i]);
271 ce.reused = 0;
272 i++;
273 }
274 // Clear 'acquired' flag in the remaining elements.
275 if (nclk_ < dst->size_)
276 CPP_STAT_INC(StatClockReleaseClearTail);
277 dst->release_store_tid_ = kInvalidTid;
278 dst->release_store_reused_ = 0;
279 // If we've acquired dst, remember this fact,
280 // so that we don't need to acquire it on next acquire.
281 if (acquired)
282 dst->elem(tid_).reused = reused_;
283}
284
285void ThreadClock::ReleaseStore(ClockCache *c, SyncClock *dst) {
286 DCHECK_LE(nclk_, kMaxTid);
287 DCHECK_LE(dst->size_, kMaxTid);
288 CPP_STAT_INC(StatClockStore);
289
290 if (dst->size_ == 0 && cached_idx_ != 0) {
291 // Reuse the cached clock.
292 // Note: we could reuse/cache the cached clock in more cases:
293 // we could update the existing clock and cache it, or replace it with the
294 // currently cached clock and release the old one. And for a shared
295 // existing clock, we could replace it with the currently cached;
296 // or unshare, update and cache. But, for simplicity, we currnetly reuse
297 // cached clock only when the target clock is empty.
298 dst->tab_ = ctx->clock_alloc.Map(cached_idx_);
299 dst->tab_idx_ = cached_idx_;
300 dst->size_ = cached_size_;
301 dst->blocks_ = cached_blocks_;
302 CHECK_EQ(dst->dirty_[0].tid, kInvalidTid);
303 // The cached clock is shared (immutable),
304 // so this is where we store the current clock.
305 dst->dirty_[0].tid = tid_;
306 dst->dirty_[0].epoch = clk_[tid_];
307 dst->release_store_tid_ = tid_;
308 dst->release_store_reused_ = reused_;
309 // Rememeber that we don't need to acquire it in future.
310 dst->elem(tid_).reused = reused_;
311 // Grab a reference.
312 atomic_fetch_add(ref_ptr(dst->tab_), 1, memory_order_relaxed);
313 return;
314 }
315
316 // Check if we need to resize dst.
317 if (dst->size_ < nclk_)
318 dst->Resize(c, nclk_);
319
320 if (dst->release_store_tid_ == tid_ &&
321 dst->release_store_reused_ == reused_ &&
322 !HasAcquiredAfterRelease(dst)) {
323 CPP_STAT_INC(StatClockStoreFast);
324 UpdateCurrentThread(c, dst);
325 return;
326 }
327
328 // O(N) release-store.
329 CPP_STAT_INC(StatClockStoreFull);
330 dst->Unshare(c);
331 // Note: dst can be larger than this ThreadClock.
332 // This is fine since clk_ beyond size is all zeros.
333 uptr i = 0;
334 for (ClockElem &ce : *dst) {
335 ce.epoch = clk_[i];
336 ce.reused = 0;
337 i++;
338 }
339 for (uptr i = 0; i < kDirtyTids; i++)
340 dst->dirty_[i].tid = kInvalidTid;
341 dst->release_store_tid_ = tid_;
342 dst->release_store_reused_ = reused_;
343 // Rememeber that we don't need to acquire it in future.
344 dst->elem(tid_).reused = reused_;
345
346 // If the resulting clock is cachable, cache it for future release operations.
347 // The clock is always cachable if we released to an empty sync object.
348 if (cached_idx_ == 0 && dst->Cachable()) {
349 // Grab a reference to the ClockBlock.
350 atomic_uint32_t *ref = ref_ptr(dst->tab_);
351 if (atomic_load(ref, memory_order_acquire) == 1)
352 atomic_store_relaxed(ref, 2);
353 else
354 atomic_fetch_add(ref_ptr(dst->tab_), 1, memory_order_relaxed);
355 cached_idx_ = dst->tab_idx_;
356 cached_size_ = dst->size_;
357 cached_blocks_ = dst->blocks_;
358 }
359}
360
361void ThreadClock::acq_rel(ClockCache *c, SyncClock *dst) {
362 CPP_STAT_INC(StatClockAcquireRelease);
363 acquire(c, dst);
364 ReleaseStore(c, dst);
365}
366
367// Updates only single element related to the current thread in dst->clk_.
368void ThreadClock::UpdateCurrentThread(ClockCache *c, SyncClock *dst) const {
369 // Update the threads time, but preserve 'acquired' flag.
370 for (unsigned i = 0; i < kDirtyTids; i++) {
371 SyncClock::Dirty *dirty = &dst->dirty_[i];
372 const unsigned tid = dirty->tid;
373 if (tid == tid_ || tid == kInvalidTid) {
374 CPP_STAT_INC(StatClockReleaseFast);
375 dirty->tid = tid_;
376 dirty->epoch = clk_[tid_];
377 return;
378 }
379 }
380 // Reset all 'acquired' flags, O(N).
381 // We are going to touch dst elements, so we need to unshare it.
382 dst->Unshare(c);
383 CPP_STAT_INC(StatClockReleaseSlow);
384 dst->elem(tid_).epoch = clk_[tid_];
385 for (uptr i = 0; i < dst->size_; i++)
386 dst->elem(i).reused = 0;
387 dst->FlushDirty();
388}
389
390// Checks whether the current thread has already acquired src.
391bool ThreadClock::IsAlreadyAcquired(const SyncClock *src) const {
392 if (src->elem(tid_).reused != reused_)
393 return false;
394 for (unsigned i = 0; i < kDirtyTids; i++) {
395 SyncClock::Dirty dirty = src->dirty_[i];
396 if (dirty.tid != kInvalidTid) {
397 if (clk_[dirty.tid] < dirty.epoch)
398 return false;
399 }
400 }
401 return true;
402}
403
404// Checks whether the current thread has acquired anything
405// from other clocks after releasing to dst (directly or indirectly).
406bool ThreadClock::HasAcquiredAfterRelease(const SyncClock *dst) const {
407 const u64 my_epoch = dst->elem(tid_).epoch;
408 return my_epoch <= last_acquire_ ||
409 my_epoch <= atomic_load_relaxed(&global_acquire_);
410}
411
412// Sets a single element in the vector clock.
413// This function is called only from weird places like AcquireGlobal.
414void ThreadClock::set(ClockCache *c, unsigned tid, u64 v) {
415 DCHECK_LT(tid, kMaxTid);
416 DCHECK_GE(v, clk_[tid]);
417 clk_[tid] = v;
418 if (nclk_ <= tid)
419 nclk_ = tid + 1;
420 last_acquire_ = clk_[tid_];
421 ResetCached(c);
422}
423
424void ThreadClock::DebugDump(int(*printf)(const char *s, ...)) {
425 printf("clock=[");
426 for (uptr i = 0; i < nclk_; i++)
427 printf("%s%llu", i == 0 ? "" : ",", clk_[i]);
428 printf("] tid=%u/%u last_acq=%llu", tid_, reused_, last_acquire_);
429}
430
431SyncClock::SyncClock() {
432 ResetImpl();
433}
434
435SyncClock::~SyncClock() {
436 // Reset must be called before dtor.
437 CHECK_EQ(size_, 0);
438 CHECK_EQ(blocks_, 0);
439 CHECK_EQ(tab_, 0);
440 CHECK_EQ(tab_idx_, 0);
441}
442
443void SyncClock::Reset(ClockCache *c) {
444 if (size_)
445 UnrefClockBlock(c, tab_idx_, blocks_);
446 ResetImpl();
447}
448
449void SyncClock::ResetImpl() {
450 tab_ = 0;
451 tab_idx_ = 0;
452 size_ = 0;
453 blocks_ = 0;
454 release_store_tid_ = kInvalidTid;
455 release_store_reused_ = 0;
456 for (uptr i = 0; i < kDirtyTids; i++)
457 dirty_[i].tid = kInvalidTid;
458}
459
460void SyncClock::Resize(ClockCache *c, uptr nclk) {
461 CPP_STAT_INC(StatClockReleaseResize);
462 Unshare(c);
463 if (nclk <= capacity()) {
464 // Memory is already allocated, just increase the size.
465 size_ = nclk;
466 return;
467 }
468 if (size_ == 0) {
469 // Grow from 0 to one-level table.
470 CHECK_EQ(size_, 0);
471 CHECK_EQ(blocks_, 0);
472 CHECK_EQ(tab_, 0);
473 CHECK_EQ(tab_idx_, 0);
474 tab_idx_ = ctx->clock_alloc.Alloc(c);
475 tab_ = ctx->clock_alloc.Map(tab_idx_);
476 internal_memset(tab_, 0, sizeof(*tab_));
477 atomic_store_relaxed(ref_ptr(tab_), 1);
478 size_ = 1;
479 } else if (size_ > blocks_ * ClockBlock::kClockCount) {
480 u32 idx = ctx->clock_alloc.Alloc(c);
481 ClockBlock *new_cb = ctx->clock_alloc.Map(idx);
482 uptr top = size_ - blocks_ * ClockBlock::kClockCount;
483 CHECK_LT(top, ClockBlock::kClockCount);
484 const uptr move = top * sizeof(tab_->clock[0]);
485 internal_memcpy(&new_cb->clock[0], tab_->clock, move);
486 internal_memset(&new_cb->clock[top], 0, sizeof(*new_cb) - move);
487 internal_memset(tab_->clock, 0, move);
488 append_block(idx);
489 }
490 // At this point we have first level table allocated and all clock elements
491 // are evacuated from it to a second level block.
492 // Add second level tables as necessary.
493 while (nclk > capacity()) {
494 u32 idx = ctx->clock_alloc.Alloc(c);
495 ClockBlock *cb = ctx->clock_alloc.Map(idx);
496 internal_memset(cb, 0, sizeof(*cb));
497 append_block(idx);
498 }
499 size_ = nclk;
500}
501
502// Flushes all dirty elements into the main clock array.
503void SyncClock::FlushDirty() {
504 for (unsigned i = 0; i < kDirtyTids; i++) {
505 Dirty *dirty = &dirty_[i];
506 if (dirty->tid != kInvalidTid) {
507 CHECK_LT(dirty->tid, size_);
508 elem(dirty->tid).epoch = dirty->epoch;
509 dirty->tid = kInvalidTid;
510 }
511 }
512}
513
514bool SyncClock::IsShared() const {
515 if (size_ == 0)
516 return false;
517 atomic_uint32_t *ref = ref_ptr(tab_);
518 u32 v = atomic_load(ref, memory_order_acquire);
519 CHECK_GT(v, 0);
520 return v > 1;
521}
522
523// Unshares the current clock if it's shared.
524// Shared clocks are immutable, so they need to be unshared before any updates.
525// Note: this does not apply to dirty entries as they are not shared.
526void SyncClock::Unshare(ClockCache *c) {
527 if (!IsShared())
528 return;
529 // First, copy current state into old.
530 SyncClock old;
531 old.tab_ = tab_;
532 old.tab_idx_ = tab_idx_;
533 old.size_ = size_;
534 old.blocks_ = blocks_;
535 old.release_store_tid_ = release_store_tid_;
536 old.release_store_reused_ = release_store_reused_;
537 for (unsigned i = 0; i < kDirtyTids; i++)
538 old.dirty_[i] = dirty_[i];
539 // Then, clear current object.
540 ResetImpl();
541 // Allocate brand new clock in the current object.
542 Resize(c, old.size_);
543 // Now copy state back into this object.
544 Iter old_iter(&old);
545 for (ClockElem &ce : *this) {
546 ce = *old_iter;
547 ++old_iter;
548 }
549 release_store_tid_ = old.release_store_tid_;
550 release_store_reused_ = old.release_store_reused_;
551 for (unsigned i = 0; i < kDirtyTids; i++)
552 dirty_[i] = old.dirty_[i];
553 // Drop reference to old and delete if necessary.
554 old.Reset(c);
555}
556
557// Can we cache this clock for future release operations?
558ALWAYS_INLINE bool SyncClock::Cachable() const {
559 if (size_ == 0)
560 return false;
561 for (unsigned i = 0; i < kDirtyTids; i++) {
562 if (dirty_[i].tid != kInvalidTid)
563 return false;
564 }
565 return atomic_load_relaxed(ref_ptr(tab_)) == 1;
566}
567
568// elem linearizes the two-level structure into linear array.
569// Note: this is used only for one time accesses, vector operations use
570// the iterator as it is much faster.
571ALWAYS_INLINE ClockElem &SyncClock::elem(unsigned tid) const {
572 DCHECK_LT(tid, size_);
573 const uptr block = tid / ClockBlock::kClockCount;
574 DCHECK_LE(block, blocks_);
575 tid %= ClockBlock::kClockCount;
576 if (block == blocks_)
577 return tab_->clock[tid];
578 u32 idx = get_block(block);
579 ClockBlock *cb = ctx->clock_alloc.Map(idx);
580 return cb->clock[tid];
581}
582
583ALWAYS_INLINE uptr SyncClock::capacity() const {
584 if (size_ == 0)
585 return 0;
586 uptr ratio = sizeof(ClockBlock::clock[0]) / sizeof(ClockBlock::table[0]);
587 // How many clock elements we can fit into the first level block.
588 // +1 for ref counter.
589 uptr top = ClockBlock::kClockCount - RoundUpTo(blocks_ + 1, ratio) / ratio;
590 return blocks_ * ClockBlock::kClockCount + top;
591}
592
593ALWAYS_INLINE u32 SyncClock::get_block(uptr bi) const {
594 DCHECK(size_);
595 DCHECK_LT(bi, blocks_);
596 return tab_->table[ClockBlock::kBlockIdx - bi];
597}
598
599ALWAYS_INLINE void SyncClock::append_block(u32 idx) {
600 uptr bi = blocks_++;
601 CHECK_EQ(get_block(bi), 0);
602 tab_->table[ClockBlock::kBlockIdx - bi] = idx;
603}
604
605// Used only by tests.
606u64 SyncClock::get(unsigned tid) const {
607 for (unsigned i = 0; i < kDirtyTids; i++) {
608 Dirty dirty = dirty_[i];
609 if (dirty.tid == tid)
610 return dirty.epoch;
611 }
612 return elem(tid).epoch;
613}
614
615// Used only by Iter test.
616u64 SyncClock::get_clean(unsigned tid) const {
617 return elem(tid).epoch;
618}
619
620void SyncClock::DebugDump(int(*printf)(const char *s, ...)) {
621 printf("clock=[");
622 for (uptr i = 0; i < size_; i++)
623 printf("%s%llu", i == 0 ? "" : ",", elem(i).epoch);
624 printf("] reused=[");
625 for (uptr i = 0; i < size_; i++)
626 printf("%s%llu", i == 0 ? "" : ",", elem(i).reused);
627 printf("] release_store_tid=%d/%d dirty_tids=%d[%llu]/%d[%llu]",
628 release_store_tid_, release_store_reused_,
629 dirty_[0].tid, dirty_[0].epoch,
630 dirty_[1].tid, dirty_[1].epoch);
631}
632
633void SyncClock::Iter::Next() {
634 // Finished with the current block, move on to the next one.
635 block_++;
636 if (block_ < parent_->blocks_) {
637 // Iterate over the next second level block.
638 u32 idx = parent_->get_block(block_);
639 ClockBlock *cb = ctx->clock_alloc.Map(idx);
640 pos_ = &cb->clock[0];
641 end_ = pos_ + min(parent_->size_ - block_ * ClockBlock::kClockCount,
642 ClockBlock::kClockCount);
643 return;
644 }
645 if (block_ == parent_->blocks_ &&
646 parent_->size_ > parent_->blocks_ * ClockBlock::kClockCount) {
647 // Iterate over elements in the first level block.
648 pos_ = &parent_->tab_->clock[0];
649 end_ = pos_ + min(parent_->size_ - block_ * ClockBlock::kClockCount,
650 ClockBlock::kClockCount);
651 return;
652 }
653 parent_ = nullptr; // denotes end
654}
655} // namespace __tsan
lib/tsan/tsan_clock.h created+283
...@@ -0,0 +1,283 @@
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<<16, 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 u64 epoch : kClkBits;
69 u64 tid : 64 - kClkBits; // kInvalidId if not active
70 };
71
72 unsigned release_store_tid_;
73 unsigned release_store_reused_;
74 Dirty dirty_[kDirtyTids];
75 // If size_ is 0, tab_ is nullptr.
76 // If size <= 64 (kClockCount), tab_ contains pointer to an array with
77 // 64 ClockElem's (ClockBlock::clock).
78 // Otherwise, tab_ points to an array with up to 127 u32 elements,
79 // each pointing to the second-level 512b block with 64 ClockElem's.
80 // Unused space in the first level ClockBlock is used to store additional
81 // clock elements.
82 // The last u32 element in the first level ClockBlock is always used as
83 // reference counter.
84 //
85 // See the following scheme for details.
86 // All memory blocks are 512 bytes (allocated from ClockAlloc).
87 // Clock (clk) elements are 64 bits.
88 // Idx and ref are 32 bits.
89 //
90 // tab_
91 // |
92 // \/
93 // +----------------------------------------------------+
94 // | clk128 | clk129 | ...unused... | idx1 | idx0 | ref |
95 // +----------------------------------------------------+
96 // | |
97 // | \/
98 // | +----------------+
99 // | | clk0 ... clk63 |
100 // | +----------------+
101 // \/
102 // +------------------+
103 // | clk64 ... clk127 |
104 // +------------------+
105 //
106 // Note: dirty entries, if active, always override what's stored in the clock.
107 ClockBlock *tab_;
108 u32 tab_idx_;
109 u16 size_;
110 u16 blocks_; // Number of second level blocks.
111
112 void Unshare(ClockCache *c);
113 bool IsShared() const;
114 bool Cachable() const;
115 void ResetImpl();
116 void FlushDirty();
117 uptr capacity() const;
118 u32 get_block(uptr bi) const;
119 void append_block(u32 idx);
120 ClockElem &elem(unsigned tid) const;
121};
122
123// The clock that lives in threads.
124class ThreadClock {
125 public:
126 typedef DenseSlabAllocCache Cache;
127
128 explicit ThreadClock(unsigned tid, unsigned reused = 0);
129
130 u64 get(unsigned tid) const;
131 void set(ClockCache *c, unsigned tid, u64 v);
132 void set(u64 v);
133 void tick();
134 uptr size() const;
135
136 void acquire(ClockCache *c, SyncClock *src);
137 void releaseStoreAcquire(ClockCache *c, SyncClock *src);
138 void release(ClockCache *c, SyncClock *dst);
139 void acq_rel(ClockCache *c, SyncClock *dst);
140 void ReleaseStore(ClockCache *c, SyncClock *dst);
141 void ResetCached(ClockCache *c);
142 void NoteGlobalAcquire(u64 v);
143
144 void DebugReset();
145 void DebugDump(int(*printf)(const char *s, ...));
146
147 private:
148 static const uptr kDirtyTids = SyncClock::kDirtyTids;
149 // Index of the thread associated with he clock ("current thread").
150 const unsigned tid_;
151 const unsigned reused_; // tid_ reuse count.
152 // Current thread time when it acquired something from other threads.
153 u64 last_acquire_;
154
155 // Last time another thread has done a global acquire of this thread's clock.
156 // It helps to avoid problem described in:
157 // https://github.com/golang/go/issues/39186
158 // See test/tsan/java_finalizer2.cpp for a regression test.
159 // Note the failuire is _extremely_ hard to hit, so if you are trying
160 // to reproduce it, you may want to run something like:
161 // $ go get golang.org/x/tools/cmd/stress
162 // $ stress -p=64 ./a.out
163 //
164 // The crux of the problem is roughly as follows.
165 // A number of O(1) optimizations in the clocks algorithm assume proper
166 // transitive cumulative propagation of clock values. The AcquireGlobal
167 // operation may produce an inconsistent non-linearazable view of
168 // thread clocks. Namely, it may acquire a later value from a thread
169 // with a higher ID, but fail to acquire an earlier value from a thread
170 // with a lower ID. If a thread that executed AcquireGlobal then releases
171 // to a sync clock, it will spoil the sync clock with the inconsistent
172 // values. If another thread later releases to the sync clock, the optimized
173 // algorithm may break.
174 //
175 // The exact sequence of events that leads to the failure.
176 // - thread 1 executes AcquireGlobal
177 // - thread 1 acquires value 1 for thread 2
178 // - thread 2 increments clock to 2
179 // - thread 2 releases to sync object 1
180 // - thread 3 at time 1
181 // - thread 3 acquires from sync object 1
182 // - thread 3 increments clock to 2
183 // - thread 1 acquires value 2 for thread 3
184 // - thread 1 releases to sync object 2
185 // - sync object 2 clock has 1 for thread 2 and 2 for thread 3
186 // - thread 3 releases to sync object 2
187 // - thread 3 sees value 2 in the clock for itself
188 // and decides that it has already released to the clock
189 // and did not acquire anything from other threads after that
190 // (the last_acquire_ check in release operation)
191 // - thread 3 does not update the value for thread 2 in the clock from 1 to 2
192 // - thread 4 acquires from sync object 2
193 // - thread 4 detects a false race with thread 2
194 // as it should have been synchronized with thread 2 up to time 2,
195 // but because of the broken clock it is now synchronized only up to time 1
196 //
197 // The global_acquire_ value helps to prevent this scenario.
198 // Namely, thread 3 will not trust any own clock values up to global_acquire_
199 // for the purposes of the last_acquire_ optimization.
200 atomic_uint64_t global_acquire_;
201
202 // Cached SyncClock (without dirty entries and release_store_tid_).
203 // We reuse it for subsequent store-release operations without intervening
204 // acquire operations. Since it is shared (and thus constant), clock value
205 // for the current thread is then stored in dirty entries in the SyncClock.
206 // We host a refernece to the table while it is cached here.
207 u32 cached_idx_;
208 u16 cached_size_;
209 u16 cached_blocks_;
210
211 // Number of active elements in the clk_ table (the rest is zeros).
212 uptr nclk_;
213 u64 clk_[kMaxTidInClock]; // Fixed size vector clock.
214
215 bool IsAlreadyAcquired(const SyncClock *src) const;
216 bool HasAcquiredAfterRelease(const SyncClock *dst) const;
217 void UpdateCurrentThread(ClockCache *c, SyncClock *dst) const;
218};
219
220ALWAYS_INLINE u64 ThreadClock::get(unsigned tid) const {
221 DCHECK_LT(tid, kMaxTidInClock);
222 return clk_[tid];
223}
224
225ALWAYS_INLINE void ThreadClock::set(u64 v) {
226 DCHECK_GE(v, clk_[tid_]);
227 clk_[tid_] = v;
228}
229
230ALWAYS_INLINE void ThreadClock::tick() {
231 clk_[tid_]++;
232}
233
234ALWAYS_INLINE uptr ThreadClock::size() const {
235 return nclk_;
236}
237
238ALWAYS_INLINE void ThreadClock::NoteGlobalAcquire(u64 v) {
239 // Here we rely on the fact that AcquireGlobal is protected by
240 // ThreadRegistryLock, thus only one thread at a time executes it
241 // and values passed to this function should not go backwards.
242 CHECK_LE(atomic_load_relaxed(&global_acquire_), v);
243 atomic_store_relaxed(&global_acquire_, v);
244}
245
246ALWAYS_INLINE SyncClock::Iter SyncClock::begin() {
247 return Iter(this);
248}
249
250ALWAYS_INLINE SyncClock::Iter SyncClock::end() {
251 return Iter(nullptr);
252}
253
254ALWAYS_INLINE uptr SyncClock::size() const {
255 return size_;
256}
257
258ALWAYS_INLINE SyncClock::Iter::Iter(SyncClock* parent)
259 : parent_(parent)
260 , pos_(nullptr)
261 , end_(nullptr)
262 , block_(-1) {
263 if (parent)
264 Next();
265}
266
267ALWAYS_INLINE SyncClock::Iter& SyncClock::Iter::operator++() {
268 pos_++;
269 if (UNLIKELY(pos_ >= end_))
270 Next();
271 return *this;
272}
273
274ALWAYS_INLINE bool SyncClock::Iter::operator!=(const SyncClock::Iter& other) {
275 return parent_ != other.parent_;
276}
277
278ALWAYS_INLINE ClockElem &SyncClock::Iter::operator*() {
279 return *pos_;
280}
281} // namespace __tsan
282
283#endif // TSAN_CLOCK_H
lib/tsan/tsan_debugging.cpp created+262
...@@ -0,0 +1,262 @@
1//===-- tsan_debugging.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// TSan debugging API implementation.
12//===----------------------------------------------------------------------===//
13#include "tsan_interface.h"
14#include "tsan_report.h"
15#include "tsan_rtl.h"
16
17#include "sanitizer_common/sanitizer_stackdepot.h"
18
19using namespace __tsan;
20
21static const char *ReportTypeDescription(ReportType typ) {
22 switch (typ) {
23 case ReportTypeRace: return "data-race";
24 case ReportTypeVptrRace: return "data-race-vptr";
25 case ReportTypeUseAfterFree: return "heap-use-after-free";
26 case ReportTypeVptrUseAfterFree: return "heap-use-after-free-vptr";
27 case ReportTypeExternalRace: return "external-race";
28 case ReportTypeThreadLeak: return "thread-leak";
29 case ReportTypeMutexDestroyLocked: return "locked-mutex-destroy";
30 case ReportTypeMutexDoubleLock: return "mutex-double-lock";
31 case ReportTypeMutexInvalidAccess: return "mutex-invalid-access";
32 case ReportTypeMutexBadUnlock: return "mutex-bad-unlock";
33 case ReportTypeMutexBadReadLock: return "mutex-bad-read-lock";
34 case ReportTypeMutexBadReadUnlock: return "mutex-bad-read-unlock";
35 case ReportTypeSignalUnsafe: return "signal-unsafe-call";
36 case ReportTypeErrnoInSignal: return "errno-in-signal-handler";
37 case ReportTypeDeadlock: return "lock-order-inversion";
38 // No default case so compiler warns us if we miss one
39 }
40 UNREACHABLE("missing case");
41}
42
43static const char *ReportLocationTypeDescription(ReportLocationType typ) {
44 switch (typ) {
45 case ReportLocationGlobal: return "global";
46 case ReportLocationHeap: return "heap";
47 case ReportLocationStack: return "stack";
48 case ReportLocationTLS: return "tls";
49 case ReportLocationFD: return "fd";
50 // No default case so compiler warns us if we miss one
51 }
52 UNREACHABLE("missing case");
53}
54
55static void CopyTrace(SymbolizedStack *first_frame, void **trace,
56 uptr trace_size) {
57 uptr i = 0;
58 for (SymbolizedStack *frame = first_frame; frame != nullptr;
59 frame = frame->next) {
60 trace[i++] = (void *)frame->info.address;
61 if (i >= trace_size) break;
62 }
63}
64
65// Meant to be called by the debugger.
66SANITIZER_INTERFACE_ATTRIBUTE
67void *__tsan_get_current_report() {
68 return const_cast<ReportDesc*>(cur_thread()->current_report);
69}
70
71SANITIZER_INTERFACE_ATTRIBUTE
72int __tsan_get_report_data(void *report, const char **description, int *count,
73 int *stack_count, int *mop_count, int *loc_count,
74 int *mutex_count, int *thread_count,
75 int *unique_tid_count, void **sleep_trace,
76 uptr trace_size) {
77 const ReportDesc *rep = (ReportDesc *)report;
78 *description = ReportTypeDescription(rep->typ);
79 *count = rep->count;
80 *stack_count = rep->stacks.Size();
81 *mop_count = rep->mops.Size();
82 *loc_count = rep->locs.Size();
83 *mutex_count = rep->mutexes.Size();
84 *thread_count = rep->threads.Size();
85 *unique_tid_count = rep->unique_tids.Size();
86 if (rep->sleep) CopyTrace(rep->sleep->frames, sleep_trace, trace_size);
87 return 1;
88}
89
90SANITIZER_INTERFACE_ATTRIBUTE
91int __tsan_get_report_tag(void *report, uptr *tag) {
92 const ReportDesc *rep = (ReportDesc *)report;
93 *tag = rep->tag;
94 return 1;
95}
96
97SANITIZER_INTERFACE_ATTRIBUTE
98int __tsan_get_report_stack(void *report, uptr idx, void **trace,
99 uptr trace_size) {
100 const ReportDesc *rep = (ReportDesc *)report;
101 CHECK_LT(idx, rep->stacks.Size());
102 ReportStack *stack = rep->stacks[idx];
103 if (stack) CopyTrace(stack->frames, trace, trace_size);
104 return stack ? 1 : 0;
105}
106
107SANITIZER_INTERFACE_ATTRIBUTE
108int __tsan_get_report_mop(void *report, uptr idx, int *tid, void **addr,
109 int *size, int *write, int *atomic, void **trace,
110 uptr trace_size) {
111 const ReportDesc *rep = (ReportDesc *)report;
112 CHECK_LT(idx, rep->mops.Size());
113 ReportMop *mop = rep->mops[idx];
114 *tid = mop->tid;
115 *addr = (void *)mop->addr;
116 *size = mop->size;
117 *write = mop->write ? 1 : 0;
118 *atomic = mop->atomic ? 1 : 0;
119 if (mop->stack) CopyTrace(mop->stack->frames, trace, trace_size);
120 return 1;
121}
122
123SANITIZER_INTERFACE_ATTRIBUTE
124int __tsan_get_report_loc(void *report, uptr idx, const char **type,
125 void **addr, uptr *start, uptr *size, int *tid,
126 int *fd, int *suppressable, void **trace,
127 uptr trace_size) {
128 const ReportDesc *rep = (ReportDesc *)report;
129 CHECK_LT(idx, rep->locs.Size());
130 ReportLocation *loc = rep->locs[idx];
131 *type = ReportLocationTypeDescription(loc->type);
132 *addr = (void *)loc->global.start;
133 *start = loc->heap_chunk_start;
134 *size = loc->heap_chunk_size;
135 *tid = loc->tid;
136 *fd = loc->fd;
137 *suppressable = loc->suppressable;
138 if (loc->stack) CopyTrace(loc->stack->frames, trace, trace_size);
139 return 1;
140}
141
142SANITIZER_INTERFACE_ATTRIBUTE
143int __tsan_get_report_loc_object_type(void *report, uptr idx,
144 const char **object_type) {
145 const ReportDesc *rep = (ReportDesc *)report;
146 CHECK_LT(idx, rep->locs.Size());
147 ReportLocation *loc = rep->locs[idx];
148 *object_type = GetObjectTypeFromTag(loc->external_tag);
149 return 1;
150}
151
152SANITIZER_INTERFACE_ATTRIBUTE
153int __tsan_get_report_mutex(void *report, uptr idx, uptr *mutex_id, void **addr,
154 int *destroyed, void **trace, uptr trace_size) {
155 const ReportDesc *rep = (ReportDesc *)report;
156 CHECK_LT(idx, rep->mutexes.Size());
157 ReportMutex *mutex = rep->mutexes[idx];
158 *mutex_id = mutex->id;
159 *addr = (void *)mutex->addr;
160 *destroyed = mutex->destroyed;
161 if (mutex->stack) CopyTrace(mutex->stack->frames, trace, trace_size);
162 return 1;
163}
164
165SANITIZER_INTERFACE_ATTRIBUTE
166int __tsan_get_report_thread(void *report, uptr idx, int *tid, tid_t *os_id,
167 int *running, const char **name, int *parent_tid,
168 void **trace, uptr trace_size) {
169 const ReportDesc *rep = (ReportDesc *)report;
170 CHECK_LT(idx, rep->threads.Size());
171 ReportThread *thread = rep->threads[idx];
172 *tid = thread->id;
173 *os_id = thread->os_id;
174 *running = thread->running;
175 *name = thread->name;
176 *parent_tid = thread->parent_tid;
177 if (thread->stack) CopyTrace(thread->stack->frames, trace, trace_size);
178 return 1;
179}
180
181SANITIZER_INTERFACE_ATTRIBUTE
182int __tsan_get_report_unique_tid(void *report, uptr idx, int *tid) {
183 const ReportDesc *rep = (ReportDesc *)report;
184 CHECK_LT(idx, rep->unique_tids.Size());
185 *tid = rep->unique_tids[idx];
186 return 1;
187}
188
189SANITIZER_INTERFACE_ATTRIBUTE
190const char *__tsan_locate_address(uptr addr, char *name, uptr name_size,
191 uptr *region_address_ptr,
192 uptr *region_size_ptr) {
193 uptr region_address = 0;
194 uptr region_size = 0;
195 const char *region_kind = nullptr;
196 if (name && name_size > 0) name[0] = 0;
197
198 if (IsMetaMem(addr)) {
199 region_kind = "meta shadow";
200 } else if (IsShadowMem(addr)) {
201 region_kind = "shadow";
202 } else {
203 bool is_stack = false;
204 MBlock *b = 0;
205 Allocator *a = allocator();
206 if (a->PointerIsMine((void *)addr)) {
207 void *block_begin = a->GetBlockBegin((void *)addr);
208 if (block_begin) b = ctx->metamap.GetBlock((uptr)block_begin);
209 }
210
211 if (b != 0) {
212 region_address = (uptr)allocator()->GetBlockBegin((void *)addr);
213 region_size = b->siz;
214 region_kind = "heap";
215 } else {
216 // TODO(kuba.brecka): We should not lock. This is supposed to be called
217 // from within the debugger when other threads are stopped.
218 ctx->thread_registry->Lock();
219 ThreadContext *tctx = IsThreadStackOrTls(addr, &is_stack);
220 ctx->thread_registry->Unlock();
221 if (tctx) {
222 region_kind = is_stack ? "stack" : "tls";
223 } else {
224 region_kind = "global";
225 DataInfo info;
226 if (Symbolizer::GetOrInit()->SymbolizeData(addr, &info)) {
227 internal_strncpy(name, info.name, name_size);
228 region_address = info.start;
229 region_size = info.size;
230 }
231 }
232 }
233 }
234
235 CHECK(region_kind);
236 if (region_address_ptr) *region_address_ptr = region_address;
237 if (region_size_ptr) *region_size_ptr = region_size;
238 return region_kind;
239}
240
241SANITIZER_INTERFACE_ATTRIBUTE
242int __tsan_get_alloc_stack(uptr addr, uptr *trace, uptr size, int *thread_id,
243 tid_t *os_id) {
244 MBlock *b = 0;
245 Allocator *a = allocator();
246 if (a->PointerIsMine((void *)addr)) {
247 void *block_begin = a->GetBlockBegin((void *)addr);
248 if (block_begin) b = ctx->metamap.GetBlock((uptr)block_begin);
249 }
250 if (b == 0) return 0;
251
252 *thread_id = b->tid;
253 // No locking. This is supposed to be called from within the debugger when
254 // other threads are stopped.
255 ThreadContextBase *tctx = ctx->thread_registry->GetThreadLocked(b->tid);
256 *os_id = tctx->os_id;
257
258 StackTrace stack = StackDepotGet(b->stk);
259 size = Min(size, (uptr)stack.size);
260 for (uptr i = 0; i < size; i++) trace[i] = stack.trace[stack.size - i - 1];
261 return size;
262}
lib/tsan/tsan_defs.h created+195
...@@ -0,0 +1,195 @@
1//===-- tsan_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
13#ifndef TSAN_DEFS_H
14#define TSAN_DEFS_H
15
16#include "sanitizer_common/sanitizer_internal_defs.h"
17#include "sanitizer_common/sanitizer_libc.h"
18#include "tsan_stat.h"
19#include "ubsan/ubsan_platform.h"
20
21// Setup defaults for compile definitions.
22#ifndef TSAN_NO_HISTORY
23# define TSAN_NO_HISTORY 0
24#endif
25
26#ifndef TSAN_COLLECT_STATS
27# define TSAN_COLLECT_STATS 0
28#endif
29
30#ifndef TSAN_CONTAINS_UBSAN
31# if CAN_SANITIZE_UB && !SANITIZER_GO
32# define TSAN_CONTAINS_UBSAN 1
33# else
34# define TSAN_CONTAINS_UBSAN 0
35# endif
36#endif
37
38namespace __tsan {
39
40const int kClkBits = 42;
41const unsigned kMaxTidReuse = (1 << (64 - kClkBits)) - 1;
42
43struct ClockElem {
44 u64 epoch : kClkBits;
45 u64 reused : 64 - kClkBits; // tid reuse count
46};
47
48struct ClockBlock {
49 static const uptr kSize = 512;
50 static const uptr kTableSize = kSize / sizeof(u32);
51 static const uptr kClockCount = kSize / sizeof(ClockElem);
52 static const uptr kRefIdx = kTableSize - 1;
53 static const uptr kBlockIdx = kTableSize - 2;
54
55 union {
56 u32 table[kTableSize];
57 ClockElem clock[kClockCount];
58 };
59
60 ClockBlock() {
61 }
62};
63
64const int kTidBits = 13;
65// Reduce kMaxTid by kClockCount because one slot in ClockBlock table is
66// occupied by reference counter, so total number of elements we can store
67// in SyncClock is kClockCount * (kTableSize - 1).
68const unsigned kMaxTid = (1 << kTidBits) - ClockBlock::kClockCount;
69#if !SANITIZER_GO
70const unsigned kMaxTidInClock = kMaxTid * 2; // This includes msb 'freed' bit.
71#else
72const unsigned kMaxTidInClock = kMaxTid; // Go does not track freed memory.
73#endif
74const uptr kShadowStackSize = 64 * 1024;
75
76// Count of shadow values in a shadow cell.
77const uptr kShadowCnt = 4;
78
79// That many user bytes are mapped onto a single shadow cell.
80const uptr kShadowCell = 8;
81
82// Size of a single shadow value (u64).
83const uptr kShadowSize = 8;
84
85// Shadow memory is kShadowMultiplier times larger than user memory.
86const uptr kShadowMultiplier = kShadowSize * kShadowCnt / kShadowCell;
87
88// That many user bytes are mapped onto a single meta shadow cell.
89// Must be less or equal to minimal memory allocator alignment.
90const uptr kMetaShadowCell = 8;
91
92// Size of a single meta shadow value (u32).
93const uptr kMetaShadowSize = 4;
94
95#if TSAN_NO_HISTORY
96const bool kCollectHistory = false;
97#else
98const bool kCollectHistory = true;
99#endif
100
101const u16 kInvalidTid = kMaxTid + 1;
102
103// The following "build consistency" machinery ensures that all source files
104// are built in the same configuration. Inconsistent builds lead to
105// hard to debug crashes.
106#if SANITIZER_DEBUG
107void build_consistency_debug();
108#else
109void build_consistency_release();
110#endif
111
112#if TSAN_COLLECT_STATS
113void build_consistency_stats();
114#else
115void build_consistency_nostats();
116#endif
117
118static inline void USED build_consistency() {
119#if SANITIZER_DEBUG
120 build_consistency_debug();
121#else
122 build_consistency_release();
123#endif
124#if TSAN_COLLECT_STATS
125 build_consistency_stats();
126#else
127 build_consistency_nostats();
128#endif
129}
130
131template<typename T>
132T min(T a, T b) {
133 return a < b ? a : b;
134}
135
136template<typename T>
137T max(T a, T b) {
138 return a > b ? a : b;
139}
140
141template<typename T>
142T RoundUp(T p, u64 align) {
143 DCHECK_EQ(align & (align - 1), 0);
144 return (T)(((u64)p + align - 1) & ~(align - 1));
145}
146
147template<typename T>
148T RoundDown(T p, u64 align) {
149 DCHECK_EQ(align & (align - 1), 0);
150 return (T)((u64)p & ~(align - 1));
151}
152
153// Zeroizes high part, returns 'bits' lsb bits.
154template<typename T>
155T GetLsb(T v, int bits) {
156 return (T)((u64)v & ((1ull << bits) - 1));
157}
158
159struct MD5Hash {
160 u64 hash[2];
161 bool operator==(const MD5Hash &other) const;
162};
163
164MD5Hash md5_hash(const void *data, uptr size);
165
166struct Processor;
167struct ThreadState;
168class ThreadContext;
169struct Context;
170struct ReportStack;
171class ReportDesc;
172class RegionAlloc;
173
174// Descriptor of user's memory block.
175struct MBlock {
176 u64 siz : 48;
177 u64 tag : 16;
178 u32 stk;
179 u16 tid;
180};
181
182COMPILER_CHECK(sizeof(MBlock) == 16);
183
184enum ExternalTag : uptr {
185 kExternalTagNone = 0,
186 kExternalTagSwiftModifyingAccess = 1,
187 kExternalTagFirstUserAvailable = 2,
188 kExternalTagMax = 1024,
189 // Don't set kExternalTagMax over 65,536, since MBlock only stores tags
190 // as 16-bit values, see tsan_defs.h.
191};
192
193} // namespace __tsan
194
195#endif // TSAN_DEFS_H
lib/tsan/tsan_dense_alloc.h created+141
...@@ -0,0 +1,141 @@
1//===-- tsan_dense_alloc.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// A DenseSlabAlloc is a freelist-based allocator of fixed-size objects.
12// DenseSlabAllocCache is a thread-local cache for DenseSlabAlloc.
13// The only difference with traditional slab allocators is that DenseSlabAlloc
14// allocates/free indices of objects and provide a functionality to map
15// the index onto the real pointer. The index is u32, that is, 2 times smaller
16// than uptr (hense the Dense prefix).
17//===----------------------------------------------------------------------===//
18#ifndef TSAN_DENSE_ALLOC_H
19#define TSAN_DENSE_ALLOC_H
20
21#include "sanitizer_common/sanitizer_common.h"
22#include "tsan_defs.h"
23#include "tsan_mutex.h"
24
25namespace __tsan {
26
27class DenseSlabAllocCache {
28 static const uptr kSize = 128;
29 typedef u32 IndexT;
30 uptr pos;
31 IndexT cache[kSize];
32 template<typename T, uptr kL1Size, uptr kL2Size> friend class DenseSlabAlloc;
33};
34
35template<typename T, uptr kL1Size, uptr kL2Size>
36class DenseSlabAlloc {
37 public:
38 typedef DenseSlabAllocCache Cache;
39 typedef typename Cache::IndexT IndexT;
40
41 explicit DenseSlabAlloc(const char *name) {
42 // Check that kL1Size and kL2Size are sane.
43 CHECK_EQ(kL1Size & (kL1Size - 1), 0);
44 CHECK_EQ(kL2Size & (kL2Size - 1), 0);
45 CHECK_GE(1ull << (sizeof(IndexT) * 8), kL1Size * kL2Size);
46 // Check that it makes sense to use the dense alloc.
47 CHECK_GE(sizeof(T), sizeof(IndexT));
48 internal_memset(map_, 0, sizeof(map_));
49 freelist_ = 0;
50 fillpos_ = 0;
51 name_ = name;
52 }
53
54 ~DenseSlabAlloc() {
55 for (uptr i = 0; i < kL1Size; i++) {
56 if (map_[i] != 0)
57 UnmapOrDie(map_[i], kL2Size * sizeof(T));
58 }
59 }
60
61 IndexT Alloc(Cache *c) {
62 if (c->pos == 0)
63 Refill(c);
64 return c->cache[--c->pos];
65 }
66
67 void Free(Cache *c, IndexT idx) {
68 DCHECK_NE(idx, 0);
69 if (c->pos == Cache::kSize)
70 Drain(c);
71 c->cache[c->pos++] = idx;
72 }
73
74 T *Map(IndexT idx) {
75 DCHECK_NE(idx, 0);
76 DCHECK_LE(idx, kL1Size * kL2Size);
77 return &map_[idx / kL2Size][idx % kL2Size];
78 }
79
80 void FlushCache(Cache *c) {
81 SpinMutexLock lock(&mtx_);
82 while (c->pos) {
83 IndexT idx = c->cache[--c->pos];
84 *(IndexT*)Map(idx) = freelist_;
85 freelist_ = idx;
86 }
87 }
88
89 void InitCache(Cache *c) {
90 c->pos = 0;
91 internal_memset(c->cache, 0, sizeof(c->cache));
92 }
93
94 private:
95 T *map_[kL1Size];
96 SpinMutex mtx_;
97 IndexT freelist_;
98 uptr fillpos_;
99 const char *name_;
100
101 void Refill(Cache *c) {
102 SpinMutexLock lock(&mtx_);
103 if (freelist_ == 0) {
104 if (fillpos_ == kL1Size) {
105 Printf("ThreadSanitizer: %s overflow (%zu*%zu). Dying.\n",
106 name_, kL1Size, kL2Size);
107 Die();
108 }
109 VPrintf(2, "ThreadSanitizer: growing %s: %zu out of %zu*%zu\n",
110 name_, fillpos_, kL1Size, kL2Size);
111 T *batch = (T*)MmapOrDie(kL2Size * sizeof(T), name_);
112 // Reserve 0 as invalid index.
113 IndexT start = fillpos_ == 0 ? 1 : 0;
114 for (IndexT i = start; i < kL2Size; i++) {
115 new(batch + i) T;
116 *(IndexT*)(batch + i) = i + 1 + fillpos_ * kL2Size;
117 }
118 *(IndexT*)(batch + kL2Size - 1) = 0;
119 freelist_ = fillpos_ * kL2Size + start;
120 map_[fillpos_++] = batch;
121 }
122 for (uptr i = 0; i < Cache::kSize / 2 && freelist_ != 0; i++) {
123 IndexT idx = freelist_;
124 c->cache[c->pos++] = idx;
125 freelist_ = *(IndexT*)Map(idx);
126 }
127 }
128
129 void Drain(Cache *c) {
130 SpinMutexLock lock(&mtx_);
131 for (uptr i = 0; i < Cache::kSize / 2; i++) {
132 IndexT idx = c->cache[--c->pos];
133 *(IndexT*)Map(idx) = freelist_;
134 freelist_ = idx;
135 }
136 }
137};
138
139} // namespace __tsan
140
141#endif // TSAN_DENSE_ALLOC_H
lib/tsan/tsan_external.cpp created+124
...@@ -0,0 +1,124 @@
1//===-- tsan_external.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_rtl.h"
13#include "tsan_interceptors.h"
14
15namespace __tsan {
16
17#define CALLERPC ((uptr)__builtin_return_address(0))
18
19struct TagData {
20 const char *object_type;
21 const char *header;
22};
23
24static TagData registered_tags[kExternalTagMax] = {
25 {},
26 {"Swift variable", "Swift access race"},
27};
28static atomic_uint32_t used_tags{kExternalTagFirstUserAvailable};
29static TagData *GetTagData(uptr tag) {
30 // Invalid/corrupted tag? Better return NULL and let the caller deal with it.
31 if (tag >= atomic_load(&used_tags, memory_order_relaxed)) return nullptr;
32 return &registered_tags[tag];
33}
34
35const char *GetObjectTypeFromTag(uptr tag) {
36 TagData *tag_data = GetTagData(tag);
37 return tag_data ? tag_data->object_type : nullptr;
38}
39
40const char *GetReportHeaderFromTag(uptr tag) {
41 TagData *tag_data = GetTagData(tag);
42 return tag_data ? tag_data->header : nullptr;
43}
44
45void InsertShadowStackFrameForTag(ThreadState *thr, uptr tag) {
46 FuncEntry(thr, (uptr)&registered_tags[tag]);
47}
48
49uptr TagFromShadowStackFrame(uptr pc) {
50 uptr tag_count = atomic_load(&used_tags, memory_order_relaxed);
51 void *pc_ptr = (void *)pc;
52 if (pc_ptr < GetTagData(0) || pc_ptr > GetTagData(tag_count - 1))
53 return 0;
54 return (TagData *)pc_ptr - GetTagData(0);
55}
56
57#if !SANITIZER_GO
58
59typedef void(*AccessFunc)(ThreadState *, uptr, uptr, int);
60void ExternalAccess(void *addr, void *caller_pc, void *tag, AccessFunc access) {
61 CHECK_LT(tag, atomic_load(&used_tags, memory_order_relaxed));
62 ThreadState *thr = cur_thread();
63 if (caller_pc) FuncEntry(thr, (uptr)caller_pc);
64 InsertShadowStackFrameForTag(thr, (uptr)tag);
65 bool in_ignored_lib;
66 if (!caller_pc || !libignore()->IsIgnored((uptr)caller_pc, &in_ignored_lib)) {
67 access(thr, CALLERPC, (uptr)addr, kSizeLog1);
68 }
69 FuncExit(thr);
70 if (caller_pc) FuncExit(thr);
71}
72
73extern "C" {
74SANITIZER_INTERFACE_ATTRIBUTE
75void *__tsan_external_register_tag(const char *object_type) {
76 uptr new_tag = atomic_fetch_add(&used_tags, 1, memory_order_relaxed);
77 CHECK_LT(new_tag, kExternalTagMax);
78 GetTagData(new_tag)->object_type = internal_strdup(object_type);
79 char header[127] = {0};
80 internal_snprintf(header, sizeof(header), "race on %s", object_type);
81 GetTagData(new_tag)->header = internal_strdup(header);
82 return (void *)new_tag;
83}
84
85SANITIZER_INTERFACE_ATTRIBUTE
86void __tsan_external_register_header(void *tag, const char *header) {
87 CHECK_GE((uptr)tag, kExternalTagFirstUserAvailable);
88 CHECK_LT((uptr)tag, kExternalTagMax);
89 atomic_uintptr_t *header_ptr =
90 (atomic_uintptr_t *)&GetTagData((uptr)tag)->header;
91 header = internal_strdup(header);
92 char *old_header =
93 (char *)atomic_exchange(header_ptr, (uptr)header, memory_order_seq_cst);
94 if (old_header) internal_free(old_header);
95}
96
97SANITIZER_INTERFACE_ATTRIBUTE
98void __tsan_external_assign_tag(void *addr, void *tag) {
99 CHECK_LT(tag, atomic_load(&used_tags, memory_order_relaxed));
100 Allocator *a = allocator();
101 MBlock *b = nullptr;
102 if (a->PointerIsMine((void *)addr)) {
103 void *block_begin = a->GetBlockBegin((void *)addr);
104 if (block_begin) b = ctx->metamap.GetBlock((uptr)block_begin);
105 }
106 if (b) {
107 b->tag = (uptr)tag;
108 }
109}
110
111SANITIZER_INTERFACE_ATTRIBUTE
112void __tsan_external_read(void *addr, void *caller_pc, void *tag) {
113 ExternalAccess(addr, caller_pc, tag, MemoryRead);
114}
115
116SANITIZER_INTERFACE_ATTRIBUTE
117void __tsan_external_write(void *addr, void *caller_pc, void *tag) {
118 ExternalAccess(addr, caller_pc, tag, MemoryWrite);
119}
120} // extern "C"
121
122#endif // !SANITIZER_GO
123
124} // namespace __tsan
lib/tsan/tsan_fd.cpp created+316
...@@ -0,0 +1,316 @@
1//===-- tsan_fd.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#include "tsan_fd.h"
14#include "tsan_rtl.h"
15#include <sanitizer_common/sanitizer_atomic.h>
16
17namespace __tsan {
18
19const int kTableSizeL1 = 1024;
20const int kTableSizeL2 = 1024;
21const int kTableSize = kTableSizeL1 * kTableSizeL2;
22
23struct FdSync {
24 atomic_uint64_t rc;
25};
26
27struct FdDesc {
28 FdSync *sync;
29 int creation_tid;
30 u32 creation_stack;
31};
32
33struct FdContext {
34 atomic_uintptr_t tab[kTableSizeL1];
35 // Addresses used for synchronization.
36 FdSync globsync;
37 FdSync filesync;
38 FdSync socksync;
39 u64 connectsync;
40};
41
42static FdContext fdctx;
43
44static bool bogusfd(int fd) {
45 // Apparently a bogus fd value.
46 return fd < 0 || fd >= kTableSize;
47}
48
49static FdSync *allocsync(ThreadState *thr, uptr pc) {
50 FdSync *s = (FdSync*)user_alloc_internal(thr, pc, sizeof(FdSync),
51 kDefaultAlignment, false);
52 atomic_store(&s->rc, 1, memory_order_relaxed);
53 return s;
54}
55
56static FdSync *ref(FdSync *s) {
57 if (s && atomic_load(&s->rc, memory_order_relaxed) != (u64)-1)
58 atomic_fetch_add(&s->rc, 1, memory_order_relaxed);
59 return s;
60}
61
62static void unref(ThreadState *thr, uptr pc, FdSync *s) {
63 if (s && atomic_load(&s->rc, memory_order_relaxed) != (u64)-1) {
64 if (atomic_fetch_sub(&s->rc, 1, memory_order_acq_rel) == 1) {
65 CHECK_NE(s, &fdctx.globsync);
66 CHECK_NE(s, &fdctx.filesync);
67 CHECK_NE(s, &fdctx.socksync);
68 user_free(thr, pc, s, false);
69 }
70 }
71}
72
73static FdDesc *fddesc(ThreadState *thr, uptr pc, int fd) {
74 CHECK_GE(fd, 0);
75 CHECK_LT(fd, kTableSize);
76 atomic_uintptr_t *pl1 = &fdctx.tab[fd / kTableSizeL2];
77 uptr l1 = atomic_load(pl1, memory_order_consume);
78 if (l1 == 0) {
79 uptr size = kTableSizeL2 * sizeof(FdDesc);
80 // We need this to reside in user memory to properly catch races on it.
81 void *p = user_alloc_internal(thr, pc, size, kDefaultAlignment, false);
82 internal_memset(p, 0, size);
83 MemoryResetRange(thr, (uptr)&fddesc, (uptr)p, size);
84 if (atomic_compare_exchange_strong(pl1, &l1, (uptr)p, memory_order_acq_rel))
85 l1 = (uptr)p;
86 else
87 user_free(thr, pc, p, false);
88 }
89 FdDesc *fds = reinterpret_cast<FdDesc *>(l1);
90 return &fds[fd % kTableSizeL2];
91}
92
93// pd must be already ref'ed.
94static void init(ThreadState *thr, uptr pc, int fd, FdSync *s,
95 bool write = true) {
96 FdDesc *d = fddesc(thr, pc, fd);
97 // As a matter of fact, we don't intercept all close calls.
98 // See e.g. libc __res_iclose().
99 if (d->sync) {
100 unref(thr, pc, d->sync);
101 d->sync = 0;
102 }
103 if (flags()->io_sync == 0) {
104 unref(thr, pc, s);
105 } else if (flags()->io_sync == 1) {
106 d->sync = s;
107 } else if (flags()->io_sync == 2) {
108 unref(thr, pc, s);
109 d->sync = &fdctx.globsync;
110 }
111 d->creation_tid = thr->tid;
112 d->creation_stack = CurrentStackId(thr, pc);
113 if (write) {
114 // To catch races between fd usage and open.
115 MemoryRangeImitateWrite(thr, pc, (uptr)d, 8);
116 } else {
117 // See the dup-related comment in FdClose.
118 MemoryRead(thr, pc, (uptr)d, kSizeLog8);
119 }
120}
121
122void FdInit() {
123 atomic_store(&fdctx.globsync.rc, (u64)-1, memory_order_relaxed);
124 atomic_store(&fdctx.filesync.rc, (u64)-1, memory_order_relaxed);
125 atomic_store(&fdctx.socksync.rc, (u64)-1, memory_order_relaxed);
126}
127
128void FdOnFork(ThreadState *thr, uptr pc) {
129 // On fork() we need to reset all fd's, because the child is going
130 // close all them, and that will cause races between previous read/write
131 // and the close.
132 for (int l1 = 0; l1 < kTableSizeL1; l1++) {
133 FdDesc *tab = (FdDesc*)atomic_load(&fdctx.tab[l1], memory_order_relaxed);
134 if (tab == 0)
135 break;
136 for (int l2 = 0; l2 < kTableSizeL2; l2++) {
137 FdDesc *d = &tab[l2];
138 MemoryResetRange(thr, pc, (uptr)d, 8);
139 }
140 }
141}
142
143bool FdLocation(uptr addr, int *fd, int *tid, u32 *stack) {
144 for (int l1 = 0; l1 < kTableSizeL1; l1++) {
145 FdDesc *tab = (FdDesc*)atomic_load(&fdctx.tab[l1], memory_order_relaxed);
146 if (tab == 0)
147 break;
148 if (addr >= (uptr)tab && addr < (uptr)(tab + kTableSizeL2)) {
149 int l2 = (addr - (uptr)tab) / sizeof(FdDesc);
150 FdDesc *d = &tab[l2];
151 *fd = l1 * kTableSizeL1 + l2;
152 *tid = d->creation_tid;
153 *stack = d->creation_stack;
154 return true;
155 }
156 }
157 return false;
158}
159
160void FdAcquire(ThreadState *thr, uptr pc, int fd) {
161 if (bogusfd(fd))
162 return;
163 FdDesc *d = fddesc(thr, pc, fd);
164 FdSync *s = d->sync;
165 DPrintf("#%d: FdAcquire(%d) -> %p\n", thr->tid, fd, s);
166 MemoryRead(thr, pc, (uptr)d, kSizeLog8);
167 if (s)
168 Acquire(thr, pc, (uptr)s);
169}
170
171void FdRelease(ThreadState *thr, uptr pc, int fd) {
172 if (bogusfd(fd))
173 return;
174 FdDesc *d = fddesc(thr, pc, fd);
175 FdSync *s = d->sync;
176 DPrintf("#%d: FdRelease(%d) -> %p\n", thr->tid, fd, s);
177 MemoryRead(thr, pc, (uptr)d, kSizeLog8);
178 if (s)
179 Release(thr, pc, (uptr)s);
180}
181
182void FdAccess(ThreadState *thr, uptr pc, int fd) {
183 DPrintf("#%d: FdAccess(%d)\n", thr->tid, fd);
184 if (bogusfd(fd))
185 return;
186 FdDesc *d = fddesc(thr, pc, fd);
187 MemoryRead(thr, pc, (uptr)d, kSizeLog8);
188}
189
190void FdClose(ThreadState *thr, uptr pc, int fd, bool write) {
191 DPrintf("#%d: FdClose(%d)\n", thr->tid, fd);
192 if (bogusfd(fd))
193 return;
194 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);
208 }
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);
212 unref(thr, pc, d->sync);
213 d->sync = 0;
214 d->creation_tid = 0;
215 d->creation_stack = 0;
216}
217
218void FdFileCreate(ThreadState *thr, uptr pc, int fd) {
219 DPrintf("#%d: FdFileCreate(%d)\n", thr->tid, fd);
220 if (bogusfd(fd))
221 return;
222 init(thr, pc, fd, &fdctx.filesync);
223}
224
225void FdDup(ThreadState *thr, uptr pc, int oldfd, int newfd, bool write) {
226 DPrintf("#%d: FdDup(%d, %d)\n", thr->tid, oldfd, newfd);
227 if (bogusfd(oldfd) || bogusfd(newfd))
228 return;
229 // Ignore the case when user dups not yet connected socket.
230 FdDesc *od = fddesc(thr, pc, oldfd);
231 MemoryRead(thr, pc, (uptr)od, kSizeLog8);
232 FdClose(thr, pc, newfd, write);
233 init(thr, pc, newfd, ref(od->sync), write);
234}
235
236void FdPipeCreate(ThreadState *thr, uptr pc, int rfd, int wfd) {
237 DPrintf("#%d: FdCreatePipe(%d, %d)\n", thr->tid, rfd, wfd);
238 FdSync *s = allocsync(thr, pc);
239 init(thr, pc, rfd, ref(s));
240 init(thr, pc, wfd, ref(s));
241 unref(thr, pc, s);
242}
243
244void FdEventCreate(ThreadState *thr, uptr pc, int fd) {
245 DPrintf("#%d: FdEventCreate(%d)\n", thr->tid, fd);
246 if (bogusfd(fd))
247 return;
248 init(thr, pc, fd, allocsync(thr, pc));
249}
250
251void FdSignalCreate(ThreadState *thr, uptr pc, int fd) {
252 DPrintf("#%d: FdSignalCreate(%d)\n", thr->tid, fd);
253 if (bogusfd(fd))
254 return;
255 init(thr, pc, fd, 0);
256}
257
258void FdInotifyCreate(ThreadState *thr, uptr pc, int fd) {
259 DPrintf("#%d: FdInotifyCreate(%d)\n", thr->tid, fd);
260 if (bogusfd(fd))
261 return;
262 init(thr, pc, fd, 0);
263}
264
265void FdPollCreate(ThreadState *thr, uptr pc, int fd) {
266 DPrintf("#%d: FdPollCreate(%d)\n", thr->tid, fd);
267 if (bogusfd(fd))
268 return;
269 init(thr, pc, fd, allocsync(thr, pc));
270}
271
272void FdSocketCreate(ThreadState *thr, uptr pc, int fd) {
273 DPrintf("#%d: FdSocketCreate(%d)\n", thr->tid, fd);
274 if (bogusfd(fd))
275 return;
276 // It can be a UDP socket.
277 init(thr, pc, fd, &fdctx.socksync);
278}
279
280void FdSocketAccept(ThreadState *thr, uptr pc, int fd, int newfd) {
281 DPrintf("#%d: FdSocketAccept(%d, %d)\n", thr->tid, fd, newfd);
282 if (bogusfd(fd))
283 return;
284 // Synchronize connect->accept.
285 Acquire(thr, pc, (uptr)&fdctx.connectsync);
286 init(thr, pc, newfd, &fdctx.socksync);
287}
288
289void FdSocketConnecting(ThreadState *thr, uptr pc, int fd) {
290 DPrintf("#%d: FdSocketConnecting(%d)\n", thr->tid, fd);
291 if (bogusfd(fd))
292 return;
293 // Synchronize connect->accept.
294 Release(thr, pc, (uptr)&fdctx.connectsync);
295}
296
297void FdSocketConnect(ThreadState *thr, uptr pc, int fd) {
298 DPrintf("#%d: FdSocketConnect(%d)\n", thr->tid, fd);
299 if (bogusfd(fd))
300 return;
301 init(thr, pc, fd, &fdctx.socksync);
302}
303
304uptr File2addr(const char *path) {
305 (void)path;
306 static u64 addr;
307 return (uptr)&addr;
308}
309
310uptr Dir2addr(const char *path) {
311 (void)path;
312 static u64 addr;
313 return (uptr)&addr;
314}
315
316} // namespace __tsan
lib/tsan/tsan_fd.h created+64
...@@ -0,0 +1,64 @@
1//===-- tsan_fd.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// This file handles synchronization via IO.
12// People use IO for synchronization along the lines of:
13//
14// int X;
15// int client_socket; // initialized elsewhere
16// int server_socket; // initialized elsewhere
17//
18// Thread 1:
19// X = 42;
20// send(client_socket, ...);
21//
22// Thread 2:
23// if (recv(server_socket, ...) > 0)
24// assert(X == 42);
25//
26// This file determines the scope of the file descriptor (pipe, socket,
27// all local files, etc) and executes acquire and release operations on
28// the scope as necessary. Some scopes are very fine grained (e.g. pipe
29// operations synchronize only with operations on the same pipe), while
30// others are corse-grained (e.g. all operations on local files synchronize
31// with each other).
32//===----------------------------------------------------------------------===//
33#ifndef TSAN_FD_H
34#define TSAN_FD_H
35
36#include "tsan_rtl.h"
37
38namespace __tsan {
39
40void FdInit();
41void FdAcquire(ThreadState *thr, uptr pc, int fd);
42void FdRelease(ThreadState *thr, uptr pc, int fd);
43void FdAccess(ThreadState *thr, uptr pc, int fd);
44void FdClose(ThreadState *thr, uptr pc, int fd, bool write = true);
45void FdFileCreate(ThreadState *thr, uptr pc, int fd);
46void FdDup(ThreadState *thr, uptr pc, int oldfd, int newfd, bool write);
47void FdPipeCreate(ThreadState *thr, uptr pc, int rfd, int wfd);
48void FdEventCreate(ThreadState *thr, uptr pc, int fd);
49void FdSignalCreate(ThreadState *thr, uptr pc, int fd);
50void FdInotifyCreate(ThreadState *thr, uptr pc, int fd);
51void FdPollCreate(ThreadState *thr, uptr pc, int fd);
52void FdSocketCreate(ThreadState *thr, uptr pc, int fd);
53void FdSocketAccept(ThreadState *thr, uptr pc, int fd, int newfd);
54void FdSocketConnecting(ThreadState *thr, uptr pc, int fd);
55void FdSocketConnect(ThreadState *thr, uptr pc, int fd);
56bool FdLocation(uptr addr, int *fd, int *tid, u32 *stack);
57void FdOnFork(ThreadState *thr, uptr pc);
58
59uptr File2addr(const char *path);
60uptr Dir2addr(const char *path);
61
62} // namespace __tsan
63
64#endif // TSAN_INTERFACE_H
lib/tsan/tsan_flags.cpp created+125
...@@ -0,0 +1,125 @@
1//===-- tsan_flags.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#include "sanitizer_common/sanitizer_flags.h"
14#include "sanitizer_common/sanitizer_flag_parser.h"
15#include "sanitizer_common/sanitizer_libc.h"
16#include "tsan_flags.h"
17#include "tsan_rtl.h"
18#include "tsan_mman.h"
19#include "ubsan/ubsan_flags.h"
20
21namespace __tsan {
22
23// Can be overriden in frontend.
24#ifdef TSAN_EXTERNAL_HOOKS
25extern "C" const char* __tsan_default_options();
26#else
27SANITIZER_WEAK_DEFAULT_IMPL
28const char *__tsan_default_options() {
29 return "";
30}
31#endif
32
33void Flags::SetDefaults() {
34#define TSAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
35#include "tsan_flags.inc"
36#undef TSAN_FLAG
37 // DDFlags
38 second_deadlock_stack = false;
39}
40
41void RegisterTsanFlags(FlagParser *parser, Flags *f) {
42#define TSAN_FLAG(Type, Name, DefaultValue, Description) \
43 RegisterFlag(parser, #Name, Description, &f->Name);
44#include "tsan_flags.inc"
45#undef TSAN_FLAG
46 // DDFlags
47 RegisterFlag(parser, "second_deadlock_stack",
48 "Report where each mutex is locked in deadlock reports",
49 &f->second_deadlock_stack);
50}
51
52void InitializeFlags(Flags *f, const char *env, const char *env_option_name) {
53 SetCommonFlagsDefaults();
54 {
55 // Override some common flags defaults.
56 CommonFlags cf;
57 cf.CopyFrom(*common_flags());
58 cf.allow_addr2line = true;
59 if (SANITIZER_GO) {
60 // Does not work as expected for Go: runtime handles SIGABRT and crashes.
61 cf.abort_on_error = false;
62 // Go does not have mutexes.
63 cf.detect_deadlocks = false;
64 }
65 cf.print_suppressions = false;
66 cf.stack_trace_format = " #%n %f %S %M";
67 cf.exitcode = 66;
68 cf.intercept_tls_get_addr = true;
69 OverrideCommonFlags(cf);
70 }
71
72 f->SetDefaults();
73
74 FlagParser parser;
75 RegisterTsanFlags(&parser, f);
76 RegisterCommonFlags(&parser);
77
78#if TSAN_CONTAINS_UBSAN
79 __ubsan::Flags *uf = __ubsan::flags();
80 uf->SetDefaults();
81
82 FlagParser ubsan_parser;
83 __ubsan::RegisterUbsanFlags(&ubsan_parser, uf);
84 RegisterCommonFlags(&ubsan_parser);
85#endif
86
87 // Let a frontend override.
88 parser.ParseString(__tsan_default_options());
89#if TSAN_CONTAINS_UBSAN
90 const char *ubsan_default_options = __ubsan::MaybeCallUbsanDefaultOptions();
91 ubsan_parser.ParseString(ubsan_default_options);
92#endif
93 // Override from command line.
94 parser.ParseString(env, env_option_name);
95#if TSAN_CONTAINS_UBSAN
96 ubsan_parser.ParseStringFromEnv("UBSAN_OPTIONS");
97#endif
98
99 // Sanity check.
100 if (!f->report_bugs) {
101 f->report_thread_leaks = false;
102 f->report_destroy_locked = false;
103 f->report_signal_unsafe = false;
104 }
105
106 InitializeCommonFlags();
107
108 if (Verbosity()) ReportUnrecognizedFlags();
109
110 if (common_flags()->help) parser.PrintFlagDescriptions();
111
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
118 if (f->io_sync < 0 || f->io_sync > 2) {
119 Printf("ThreadSanitizer: incorrect value for io_sync"
120 " (must be [0..2])\n");
121 Die();
122 }
123}
124
125} // namespace __tsan
lib/tsan/tsan_flags.h created+34
...@@ -0,0 +1,34 @@
1//===-- tsan_flags.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// NOTE: This file may be included into user code.
11//===----------------------------------------------------------------------===//
12
13#ifndef TSAN_FLAGS_H
14#define TSAN_FLAGS_H
15
16#include "sanitizer_common/sanitizer_flags.h"
17#include "sanitizer_common/sanitizer_deadlock_detector_interface.h"
18
19namespace __tsan {
20
21struct Flags : DDFlags {
22#define TSAN_FLAG(Type, Name, DefaultValue, Description) Type Name;
23#include "tsan_flags.inc"
24#undef TSAN_FLAG
25
26 void SetDefaults();
27 void ParseFromString(const char *str);
28};
29
30void InitializeFlags(Flags *flags, const char *env,
31 const char *env_option_name = nullptr);
32} // namespace __tsan
33
34#endif // TSAN_FLAGS_H
lib/tsan/tsan_flags.inc created+85
...@@ -0,0 +1,85 @@
1//===-- tsan_flags.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// TSan runtime flags.
10//
11//===----------------------------------------------------------------------===//
12#ifndef TSAN_FLAG
13# error "Define TSAN_FLAG prior to including this file!"
14#endif
15
16// TSAN_FLAG(Type, Name, DefaultValue, Description)
17// See COMMON_FLAG in sanitizer_flags.inc for more details.
18
19TSAN_FLAG(bool, enable_annotations, true,
20 "Enable dynamic annotations, otherwise they are no-ops.")
21// Suppress a race report if we've already output another race report
22// with the same stack.
23TSAN_FLAG(bool, suppress_equal_stacks, true,
24 "Suppress a race report if we've already output another race report "
25 "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
30TSAN_FLAG(bool, report_bugs, true,
31 "Turns off bug reporting entirely (useful for benchmarking).")
32TSAN_FLAG(bool, report_thread_leaks, true, "Report thread leaks at exit?")
33TSAN_FLAG(bool, report_destroy_locked, true,
34 "Report destruction of a locked mutex?")
35TSAN_FLAG(bool, report_mutex_bugs, true,
36 "Report incorrect usages of mutexes and mutex annotations?")
37TSAN_FLAG(bool, report_signal_unsafe, true,
38 "Report violations of async signal-safety "
39 "(e.g. malloc() call from a signal handler).")
40TSAN_FLAG(bool, report_atomic_races, true,
41 "Report races between atomic and plain memory accesses.")
42TSAN_FLAG(
43 bool, force_seq_cst_atomics, false,
44 "If set, all atomics are effectively sequentially consistent (seq_cst), "
45 "regardless of what user actually specified.")
46TSAN_FLAG(bool, print_benign, false, "Print matched \"benign\" races at exit.")
47TSAN_FLAG(bool, halt_on_error, false, "Exit after first reported error.")
48TSAN_FLAG(int, atexit_sleep_ms, 1000,
49 "Sleep in main thread before exiting for that many ms "
50 "(useful to catch \"at exit\" races).")
51TSAN_FLAG(const char *, profile_memory, "",
52 "If set, periodically write memory profile to that file.")
53TSAN_FLAG(int, flush_memory_ms, 0, "Flush shadow memory every X ms.")
54TSAN_FLAG(int, flush_symbolizer_ms, 5000, "Flush symbolizer caches every X ms.")
55TSAN_FLAG(
56 int, memory_limit_mb, 0,
57 "Resident memory limit in MB to aim at."
58 "If the process consumes more memory, then TSan will flush shadow memory.")
59TSAN_FLAG(bool, stop_on_start, false,
60 "Stops on start until __tsan_resume() is called (for debugging).")
61TSAN_FLAG(bool, running_on_valgrind, false,
62 "Controls whether RunningOnValgrind() returns true or false.")
63// There are a lot of goroutines in Go, so we use smaller history.
64TSAN_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).")
71TSAN_FLAG(int, io_sync, 1,
72 "Controls level of synchronization implied by IO operations. "
73 "0 - no synchronization "
74 "1 - reasonable level of synchronization (write->read)"
75 "2 - global synchronization of all IO operations.")
76TSAN_FLAG(bool, die_after_fork, true,
77 "Die after multi-threaded fork if the child creates new threads.")
78TSAN_FLAG(const char *, suppressions, "", "Suppressions file name.")
79TSAN_FLAG(bool, ignore_interceptors_accesses, SANITIZER_MAC ? true : false,
80 "Ignore reads and writes from all interceptors.")
81TSAN_FLAG(bool, ignore_noninstrumented_modules, SANITIZER_MAC ? true : false,
82 "Interceptors should only detect races when called from instrumented "
83 "modules.")
84TSAN_FLAG(bool, shared_ptr_interceptor, true,
85 "Track atomic reference counting in libc++ shared_ptr and weak_ptr.")
lib/tsan/tsan_ignoreset.cpp created+46
...@@ -0,0 +1,46 @@
1//===-- tsan_ignoreset.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_ignoreset.h"
13
14namespace __tsan {
15
16const uptr IgnoreSet::kMaxSize;
17
18IgnoreSet::IgnoreSet()
19 : size_() {
20}
21
22void IgnoreSet::Add(u32 stack_id) {
23 if (size_ == kMaxSize)
24 return;
25 for (uptr i = 0; i < size_; i++) {
26 if (stacks_[i] == stack_id)
27 return;
28 }
29 stacks_[size_++] = stack_id;
30}
31
32void IgnoreSet::Reset() {
33 size_ = 0;
34}
35
36uptr IgnoreSet::Size() const {
37 return size_;
38}
39
40u32 IgnoreSet::At(uptr i) const {
41 CHECK_LT(i, size_);
42 CHECK_LE(size_, kMaxSize);
43 return stacks_[i];
44}
45
46} // namespace __tsan
lib/tsan/tsan_ignoreset.h created+37
...@@ -0,0 +1,37 @@
1//===-- tsan_ignoreset.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// IgnoreSet holds a set of stack traces where ignores were enabled.
12//===----------------------------------------------------------------------===//
13#ifndef TSAN_IGNORESET_H
14#define TSAN_IGNORESET_H
15
16#include "tsan_defs.h"
17
18namespace __tsan {
19
20class IgnoreSet {
21 public:
22 static const uptr kMaxSize = 16;
23
24 IgnoreSet();
25 void Add(u32 stack_id);
26 void Reset();
27 uptr Size() const;
28 u32 At(uptr i) const;
29
30 private:
31 uptr size_;
32 u32 stacks_[kMaxSize];
33};
34
35} // namespace __tsan
36
37#endif // TSAN_IGNORESET_H
lib/tsan/tsan_interceptors.h created+76
...@@ -0,0 +1,76 @@
1#ifndef TSAN_INTERCEPTORS_H
2#define TSAN_INTERCEPTORS_H
3
4#include "sanitizer_common/sanitizer_stacktrace.h"
5#include "tsan_rtl.h"
6
7namespace __tsan {
8
9class ScopedInterceptor {
10 public:
11 ScopedInterceptor(ThreadState *thr, const char *fname, uptr pc);
12 ~ScopedInterceptor();
13 void DisableIgnores();
14 void EnableIgnores();
15 private:
16 ThreadState *const thr_;
17 const uptr pc_;
18 bool in_ignored_lib_;
19 bool ignoring_;
20};
21
22LibIgnore *libignore();
23
24#if !SANITIZER_GO
25INLINE bool in_symbolizer() {
26 cur_thread_init();
27 return UNLIKELY(cur_thread()->in_symbolizer);
28}
29#endif
30
31} // namespace __tsan
32
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 = StackTrace::GetCurrentPc(); \
39 (void)pc; \
40/**/
41
42#define SCOPED_TSAN_INTERCEPTOR(func, ...) \
43 SCOPED_INTERCEPTOR_RAW(func, __VA_ARGS__); \
44 if (REAL(func) == 0) { \
45 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/**/
51
52#define SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START() \
53 si.DisableIgnores();
54
55#define SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END() \
56 si.EnableIgnores();
57
58#define TSAN_INTERCEPTOR(ret, func, ...) INTERCEPTOR(ret, func, __VA_ARGS__)
59
60#if SANITIZER_NETBSD
61# define TSAN_INTERCEPTOR_NETBSD_ALIAS(ret, func, ...) \
62 TSAN_INTERCEPTOR(ret, __libc_##func, __VA_ARGS__) \
63 ALIAS(WRAPPER_NAME(pthread_##func));
64# define TSAN_INTERCEPTOR_NETBSD_ALIAS_THR(ret, func, ...) \
65 TSAN_INTERCEPTOR(ret, __libc_thr_##func, __VA_ARGS__) \
66 ALIAS(WRAPPER_NAME(pthread_##func));
67# define TSAN_INTERCEPTOR_NETBSD_ALIAS_THR2(ret, func, func2, ...) \
68 TSAN_INTERCEPTOR(ret, __libc_thr_##func, __VA_ARGS__) \
69 ALIAS(WRAPPER_NAME(pthread_##func2));
70#else
71# define TSAN_INTERCEPTOR_NETBSD_ALIAS(ret, func, ...)
72# define TSAN_INTERCEPTOR_NETBSD_ALIAS_THR(ret, func, ...)
73# define TSAN_INTERCEPTOR_NETBSD_ALIAS_THR2(ret, func, func2, ...)
74#endif
75
76#endif // TSAN_INTERCEPTORS_H
lib/tsan/tsan_interceptors_posix.cpp created+2854
...@@ -0,0 +1,2854 @@
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// FIXME: move as many interceptors as possible into
12// sanitizer_common/sanitizer_common_interceptors.inc
13//===----------------------------------------------------------------------===//
14
15#include "sanitizer_common/sanitizer_atomic.h"
16#include "sanitizer_common/sanitizer_errno.h"
17#include "sanitizer_common/sanitizer_libc.h"
18#include "sanitizer_common/sanitizer_linux.h"
19#include "sanitizer_common/sanitizer_platform_limits_netbsd.h"
20#include "sanitizer_common/sanitizer_platform_limits_posix.h"
21#include "sanitizer_common/sanitizer_placement_new.h"
22#include "sanitizer_common/sanitizer_posix.h"
23#include "sanitizer_common/sanitizer_stacktrace.h"
24#include "sanitizer_common/sanitizer_tls_get_addr.h"
25#include "interception/interception.h"
26#include "tsan_interceptors.h"
27#include "tsan_interface.h"
28#include "tsan_platform.h"
29#include "tsan_suppressions.h"
30#include "tsan_rtl.h"
31#include "tsan_mman.h"
32#include "tsan_fd.h"
33
34using namespace __tsan;
35
36#if SANITIZER_FREEBSD || SANITIZER_MAC
37#define stdout __stdoutp
38#define stderr __stderrp
39#endif
40
41#if SANITIZER_NETBSD
42#define dirfd(dirp) (*(int *)(dirp))
43#define fileno_unlocked(fp) \
44 (((__sanitizer_FILE *)fp)->_file == -1 \
45 ? -1 \
46 : (int)(unsigned short)(((__sanitizer_FILE *)fp)->_file))
47
48#define stdout ((__sanitizer_FILE*)&__sF[1])
49#define stderr ((__sanitizer_FILE*)&__sF[2])
50
51#define nanosleep __nanosleep50
52#define vfork __vfork14
53#endif
54
55#if SANITIZER_ANDROID
56#define mallopt(a, b)
57#endif
58
59#ifdef __mips__
60const int kSigCount = 129;
61#else
62const int kSigCount = 65;
63#endif
64
65#ifdef __mips__
66struct ucontext_t {
67 u64 opaque[768 / sizeof(u64) + 1];
68};
69#else
70struct ucontext_t {
71 // The size is determined by looking at sizeof of real ucontext_t on linux.
72 u64 opaque[936 / sizeof(u64) + 1];
73};
74#endif
75
76#if defined(__x86_64__) || defined(__mips__) || SANITIZER_PPC64V1
77#define PTHREAD_ABI_BASE "GLIBC_2.3.2"
78#elif defined(__aarch64__) || SANITIZER_PPC64V2
79#define PTHREAD_ABI_BASE "GLIBC_2.17"
80#endif
81
82extern "C" int pthread_attr_init(void *attr);
83extern "C" int pthread_attr_destroy(void *attr);
84DECLARE_REAL(int, pthread_attr_getdetachstate, void *, void *)
85extern "C" int pthread_attr_setstacksize(void *attr, uptr stacksize);
86extern "C" int pthread_key_create(unsigned *key, void (*destructor)(void* v));
87extern "C" int pthread_setspecific(unsigned key, const void *v);
88DECLARE_REAL(int, pthread_mutexattr_gettype, void *, void *)
89DECLARE_REAL(int, fflush, __sanitizer_FILE *fp)
90DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr size)
91DECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr)
92extern "C" void *pthread_self();
93extern "C" void _exit(int status);
94#if !SANITIZER_NETBSD
95extern "C" int fileno_unlocked(void *stream);
96extern "C" int dirfd(void *dirp);
97#endif
98#if !SANITIZER_FREEBSD && !SANITIZER_ANDROID && !SANITIZER_NETBSD
99extern "C" int mallopt(int param, int value);
100#endif
101#if SANITIZER_NETBSD
102extern __sanitizer_FILE __sF[];
103#else
104extern __sanitizer_FILE *stdout, *stderr;
105#endif
106#if !SANITIZER_FREEBSD && !SANITIZER_MAC && !SANITIZER_NETBSD
107const int PTHREAD_MUTEX_RECURSIVE = 1;
108const int PTHREAD_MUTEX_RECURSIVE_NP = 1;
109#else
110const int PTHREAD_MUTEX_RECURSIVE = 2;
111const int PTHREAD_MUTEX_RECURSIVE_NP = 2;
112#endif
113#if !SANITIZER_FREEBSD && !SANITIZER_MAC && !SANITIZER_NETBSD
114const int EPOLL_CTL_ADD = 1;
115#endif
116const int SIGILL = 4;
117const int SIGTRAP = 5;
118const int SIGABRT = 6;
119const int SIGFPE = 8;
120const int SIGSEGV = 11;
121const int SIGPIPE = 13;
122const int SIGTERM = 15;
123#if defined(__mips__) || SANITIZER_FREEBSD || SANITIZER_MAC || SANITIZER_NETBSD
124const int SIGBUS = 10;
125const int SIGSYS = 12;
126#else
127const int SIGBUS = 7;
128const int SIGSYS = 31;
129#endif
130void *const MAP_FAILED = (void*)-1;
131#if SANITIZER_NETBSD
132const int PTHREAD_BARRIER_SERIAL_THREAD = 1234567;
133#elif !SANITIZER_MAC
134const int PTHREAD_BARRIER_SERIAL_THREAD = -1;
135#endif
136const int MAP_FIXED = 0x10;
137typedef long long_t;
138
139// From /usr/include/unistd.h
140# define F_ULOCK 0 /* Unlock a previously locked region. */
141# define F_LOCK 1 /* Lock a region for exclusive use. */
142# define F_TLOCK 2 /* Test and lock a region for exclusive use. */
143# define F_TEST 3 /* Test a region for other processes locks. */
144
145#if SANITIZER_FREEBSD || SANITIZER_MAC || SANITIZER_NETBSD
146const int SA_SIGINFO = 0x40;
147const int SIG_SETMASK = 3;
148#elif defined(__mips__)
149const int SA_SIGINFO = 8;
150const int SIG_SETMASK = 3;
151#else
152const int SA_SIGINFO = 4;
153const int SIG_SETMASK = 2;
154#endif
155
156#define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED \
157 (cur_thread_init(), !cur_thread()->is_inited)
158
159namespace __tsan {
160struct SignalDesc {
161 bool armed;
162 bool sigaction;
163 __sanitizer_siginfo siginfo;
164 ucontext_t ctx;
165};
166
167struct ThreadSignalContext {
168 int int_signal_send;
169 atomic_uintptr_t in_blocking_func;
170 atomic_uintptr_t have_pending_signals;
171 SignalDesc pending_signals[kSigCount];
172 // emptyset and oldset are too big for stack.
173 __sanitizer_sigset_t emptyset;
174 __sanitizer_sigset_t oldset;
175};
176
177// The sole reason tsan wraps atexit callbacks is to establish synchronization
178// between callback setup and callback execution.
179struct AtExitCtx {
180 void (*f)();
181 void *arg;
182};
183
184// InterceptorContext holds all global data required for interceptors.
185// It's explicitly constructed in InitializeInterceptors with placement new
186// and is never destroyed. This allows usage of members with non-trivial
187// constructors and destructors.
188struct InterceptorContext {
189 // The object is 64-byte aligned, because we want hot data to be located
190 // in a single cache line if possible (it's accessed in every interceptor).
191 ALIGNED(64) LibIgnore libignore;
192 __sanitizer_sigaction sigactions[kSigCount];
193#if !SANITIZER_MAC && !SANITIZER_NETBSD
194 unsigned finalize_key;
195#endif
196
197 BlockingMutex atexit_mu;
198 Vector<struct AtExitCtx *> AtExitStack;
199
200 InterceptorContext()
201 : libignore(LINKER_INITIALIZED), AtExitStack() {
202 }
203};
204
205static ALIGNED(64) char interceptor_placeholder[sizeof(InterceptorContext)];
206InterceptorContext *interceptor_ctx() {
207 return reinterpret_cast<InterceptorContext*>(&interceptor_placeholder[0]);
208}
209
210LibIgnore *libignore() {
211 return &interceptor_ctx()->libignore;
212}
213
214void InitializeLibIgnore() {
215 const SuppressionContext &supp = *Suppressions();
216 const uptr n = supp.SuppressionCount();
217 for (uptr i = 0; i < n; i++) {
218 const Suppression *s = supp.SuppressionAt(i);
219 if (0 == internal_strcmp(s->type, kSuppressionLib))
220 libignore()->AddIgnoredLibrary(s->templ);
221 }
222 if (flags()->ignore_noninstrumented_modules)
223 libignore()->IgnoreNoninstrumentedModules(true);
224 libignore()->OnLibraryLoaded(0);
225}
226
227// The following two hooks can be used by for cooperative scheduling when
228// locking.
229#ifdef TSAN_EXTERNAL_HOOKS
230void OnPotentiallyBlockingRegionBegin();
231void OnPotentiallyBlockingRegionEnd();
232#else
233SANITIZER_WEAK_CXX_DEFAULT_IMPL void OnPotentiallyBlockingRegionBegin() {}
234SANITIZER_WEAK_CXX_DEFAULT_IMPL void OnPotentiallyBlockingRegionEnd() {}
235#endif
236
237} // namespace __tsan
238
239static ThreadSignalContext *SigCtx(ThreadState *thr) {
240 ThreadSignalContext *ctx = (ThreadSignalContext*)thr->signal_ctx;
241 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;
245 }
246 return ctx;
247}
248
249ScopedInterceptor::ScopedInterceptor(ThreadState *thr, const char *fname,
250 uptr pc)
251 : thr_(thr), pc_(pc), in_ignored_lib_(false), ignoring_(false) {
252 Initialize(thr);
253 if (!thr_->is_inited) return;
254 if (!thr_->ignore_interceptors) FuncEntry(thr, pc);
255 DPrintf("#%d: intercept %s()\n", thr_->tid, fname);
256 ignoring_ =
257 !thr_->in_ignored_lib && (flags()->ignore_interceptors_accesses ||
258 libignore()->IsIgnored(pc, &in_ignored_lib_));
259 EnableIgnores();
260}
261
262ScopedInterceptor::~ScopedInterceptor() {
263 if (!thr_->is_inited) return;
264 DisableIgnores();
265 if (!thr_->ignore_interceptors) {
266 ProcessPendingSignals(thr_);
267 FuncExit(thr_);
268 CheckNoLocks(thr_);
269 }
270}
271
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 }
280 }
281}
282
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 }
291 }
292}
293
294#define TSAN_INTERCEPT(func) INTERCEPT_FUNCTION(func)
295#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)
305#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)
309#endif
310
311#define READ_STRING_OF_LEN(thr, pc, s, len, n) \
312 MemoryAccessRange((thr), (pc), (uptr)(s), \
313 common_flags()->strict_string_checks ? (len) + 1 : (n), false)
314
315#define READ_STRING(thr, pc, s, n) \
316 READ_STRING_OF_LEN((thr), (pc), (s), internal_strlen(s), (n))
317
318#define BLOCK_REAL(name) (BlockingCall(thr), REAL(name))
319
320struct BlockingCall {
321 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 }
331 // When we are in a "blocking call", we process signals asynchronously
332 // (right when they arrive). In this context we do not expect to be
333 // executing any user/runtime code. The known interceptor sequence when
334 // this is not true is: pthread_join -> munmap(stack). It's fine
335 // to ignore munmap in this case -- we handle stack shadow separately.
336 thr->ignore_interceptors++;
337 }
338
339 ~BlockingCall() {
340 thr->ignore_interceptors--;
341 atomic_store(&ctx->in_blocking_func, 0, memory_order_relaxed);
342 }
343
344 ThreadState *thr;
345 ThreadSignalContext *ctx;
346};
347
348TSAN_INTERCEPTOR(unsigned, sleep, unsigned sec) {
349 SCOPED_TSAN_INTERCEPTOR(sleep, sec);
350 unsigned res = BLOCK_REAL(sleep)(sec);
351 AfterSleep(thr, pc);
352 return res;
353}
354
355TSAN_INTERCEPTOR(int, usleep, long_t usec) {
356 SCOPED_TSAN_INTERCEPTOR(usleep, usec);
357 int res = BLOCK_REAL(usleep)(usec);
358 AfterSleep(thr, pc);
359 return res;
360}
361
362TSAN_INTERCEPTOR(int, nanosleep, void *req, void *rem) {
363 SCOPED_TSAN_INTERCEPTOR(nanosleep, req, rem);
364 int res = BLOCK_REAL(nanosleep)(req, rem);
365 AfterSleep(thr, pc);
366 return res;
367}
368
369TSAN_INTERCEPTOR(int, pause, int fake) {
370 SCOPED_TSAN_INTERCEPTOR(pause, fake);
371 return BLOCK_REAL(pause)(fake);
372}
373
374static void at_exit_wrapper() {
375 AtExitCtx *ctx;
376 {
377 // Ensure thread-safety.
378 BlockingMutexLock l(&interceptor_ctx()->atexit_mu);
379
380 // Pop AtExitCtx from the top of the stack of callback functions
381 uptr element = interceptor_ctx()->AtExitStack.Size() - 1;
382 ctx = interceptor_ctx()->AtExitStack[element];
383 interceptor_ctx()->AtExitStack.PopBack();
384 }
385
386 Acquire(cur_thread(), (uptr)0, (uptr)ctx);
387 ((void(*)())ctx->f)();
388 InternalFree(ctx);
389}
390
391static void cxa_at_exit_wrapper(void *arg) {
392 Acquire(cur_thread(), 0, (uptr)arg);
393 AtExitCtx *ctx = (AtExitCtx*)arg;
394 ((void(*)(void *arg))ctx->f)(ctx->arg);
395 InternalFree(ctx);
396}
397
398static int setup_at_exit_wrapper(ThreadState *thr, uptr pc, void(*f)(),
399 void *arg, void *dso);
400
401#if !SANITIZER_ANDROID
402TSAN_INTERCEPTOR(int, atexit, void (*f)()) {
403 if (in_symbolizer())
404 return 0;
405 // We want to setup the atexit callback even if we are in ignored lib
406 // or after fork.
407 SCOPED_INTERCEPTOR_RAW(atexit, f);
408 return setup_at_exit_wrapper(thr, pc, (void(*)())f, 0, 0);
409}
410#endif
411
412TSAN_INTERCEPTOR(int, __cxa_atexit, void (*f)(void *a), void *arg, void *dso) {
413 if (in_symbolizer())
414 return 0;
415 SCOPED_TSAN_INTERCEPTOR(__cxa_atexit, f, arg, dso);
416 return setup_at_exit_wrapper(thr, pc, (void(*)())f, arg, dso);
417}
418
419static int setup_at_exit_wrapper(ThreadState *thr, uptr pc, void(*f)(),
420 void *arg, void *dso) {
421 AtExitCtx *ctx = (AtExitCtx*)InternalAlloc(sizeof(AtExitCtx));
422 ctx->f = f;
423 ctx->arg = arg;
424 Release(thr, pc, (uptr)ctx);
425 // Memory allocation in __cxa_atexit will race with free during exit,
426 // because we do not see synchronization around atexit callback list.
427 ThreadIgnoreBegin(thr, pc);
428 int res;
429 if (!dso) {
430 // NetBSD does not preserve the 2nd argument if dso is equal to 0
431 // Store ctx in a local stack-like structure
432
433 // Ensure thread-safety.
434 BlockingMutexLock l(&interceptor_ctx()->atexit_mu);
435
436 res = REAL(__cxa_atexit)((void (*)(void *a))at_exit_wrapper, 0, 0);
437 // Push AtExitCtx on the top of the stack of callback functions
438 if (!res) {
439 interceptor_ctx()->AtExitStack.PushBack(ctx);
440 }
441 } else {
442 res = REAL(__cxa_atexit)(cxa_at_exit_wrapper, ctx, dso);
443 }
444 ThreadIgnoreEnd(thr, pc);
445 return res;
446}
447
448#if !SANITIZER_MAC && !SANITIZER_NETBSD
449static void on_exit_wrapper(int status, void *arg) {
450 ThreadState *thr = cur_thread();
451 uptr pc = 0;
452 Acquire(thr, pc, (uptr)arg);
453 AtExitCtx *ctx = (AtExitCtx*)arg;
454 ((void(*)(int status, void *arg))ctx->f)(status, ctx->arg);
455 InternalFree(ctx);
456}
457
458TSAN_INTERCEPTOR(int, on_exit, void(*f)(int, void*), void *arg) {
459 if (in_symbolizer())
460 return 0;
461 SCOPED_TSAN_INTERCEPTOR(on_exit, f, arg);
462 AtExitCtx *ctx = (AtExitCtx*)InternalAlloc(sizeof(AtExitCtx));
463 ctx->f = (void(*)())f;
464 ctx->arg = arg;
465 Release(thr, pc, (uptr)ctx);
466 // Memory allocation in __cxa_atexit will race with free during exit,
467 // because we do not see synchronization around atexit callback list.
468 ThreadIgnoreBegin(thr, pc);
469 int res = REAL(on_exit)(on_exit_wrapper, ctx);
470 ThreadIgnoreEnd(thr, pc);
471 return res;
472}
473#define TSAN_MAYBE_INTERCEPT_ON_EXIT TSAN_INTERCEPT(on_exit)
474#else
475#define TSAN_MAYBE_INTERCEPT_ON_EXIT
476#endif
477
478// Cleanup old bufs.
479static void JmpBufGarbageCollect(ThreadState *thr, uptr sp) {
480 for (uptr i = 0; i < thr->jmp_bufs.Size(); i++) {
481 JmpBuf *buf = &thr->jmp_bufs[i];
482 if (buf->sp <= sp) {
483 uptr sz = thr->jmp_bufs.Size();
484 internal_memcpy(buf, &thr->jmp_bufs[sz - 1], sizeof(*buf));
485 thr->jmp_bufs.PopBack();
486 i--;
487 }
488 }
489}
490
491static void SetJmp(ThreadState *thr, uptr sp) {
492 if (!thr->is_inited) // called from libc guts during bootstrap
493 return;
494 // Cleanup old bufs.
495 JmpBufGarbageCollect(thr, sp);
496 // Remember the buf.
497 JmpBuf *buf = thr->jmp_bufs.PushBack();
498 buf->sp = sp;
499 buf->shadow_stack_pos = thr->shadow_stack_pos;
500 ThreadSignalContext *sctx = SigCtx(thr);
501 buf->int_signal_send = sctx ? sctx->int_signal_send : 0;
502 buf->in_blocking_func = sctx ?
503 atomic_load(&sctx->in_blocking_func, memory_order_relaxed) :
504 false;
505 buf->in_signal_handler = atomic_load(&thr->in_signal_handler,
506 memory_order_relaxed);
507}
508
509static void LongJmp(ThreadState *thr, uptr *env) {
510 uptr sp = ExtractLongJmpSp(env);
511 // Find the saved buf with matching sp.
512 for (uptr i = 0; i < thr->jmp_bufs.Size(); i++) {
513 JmpBuf *buf = &thr->jmp_bufs[i];
514 if (buf->sp == sp) {
515 CHECK_GE(thr->shadow_stack_pos, buf->shadow_stack_pos);
516 // Unwind the stack.
517 while (thr->shadow_stack_pos > buf->shadow_stack_pos)
518 FuncExit(thr);
519 ThreadSignalContext *sctx = SigCtx(thr);
520 if (sctx) {
521 sctx->int_signal_send = buf->int_signal_send;
522 atomic_store(&sctx->in_blocking_func, buf->in_blocking_func,
523 memory_order_relaxed);
524 }
525 atomic_store(&thr->in_signal_handler, buf->in_signal_handler,
526 memory_order_relaxed);
527 JmpBufGarbageCollect(thr, buf->sp - 1); // do not collect buf->sp
528 return;
529 }
530 }
531 Printf("ThreadSanitizer: can't find longjmp buf\n");
532 CHECK(0);
533}
534
535// FIXME: put everything below into a common extern "C" block?
536extern "C" void __tsan_setjmp(uptr sp) {
537 cur_thread_init();
538 SetJmp(cur_thread(), sp);
539}
540
541#if SANITIZER_MAC
542TSAN_INTERCEPTOR(int, setjmp, void *env);
543TSAN_INTERCEPTOR(int, _setjmp, void *env);
544TSAN_INTERCEPTOR(int, sigsetjmp, void *env);
545#else // SANITIZER_MAC
546
547#if SANITIZER_NETBSD
548#define setjmp_symname __setjmp14
549#define sigsetjmp_symname __sigsetjmp14
550#else
551#define setjmp_symname setjmp
552#define sigsetjmp_symname sigsetjmp
553#endif
554
555#define TSAN_INTERCEPTOR_SETJMP_(x) __interceptor_ ## x
556#define TSAN_INTERCEPTOR_SETJMP__(x) TSAN_INTERCEPTOR_SETJMP_(x)
557#define TSAN_INTERCEPTOR_SETJMP TSAN_INTERCEPTOR_SETJMP__(setjmp_symname)
558#define TSAN_INTERCEPTOR_SIGSETJMP TSAN_INTERCEPTOR_SETJMP__(sigsetjmp_symname)
559
560#define TSAN_STRING_SETJMP SANITIZER_STRINGIFY(setjmp_symname)
561#define TSAN_STRING_SIGSETJMP SANITIZER_STRINGIFY(sigsetjmp_symname)
562
563// Not called. Merely to satisfy TSAN_INTERCEPT().
564extern "C" SANITIZER_INTERFACE_ATTRIBUTE
565int TSAN_INTERCEPTOR_SETJMP(void *env);
566extern "C" int TSAN_INTERCEPTOR_SETJMP(void *env) {
567 CHECK(0);
568 return 0;
569}
570
571// FIXME: any reason to have a separate declaration?
572extern "C" SANITIZER_INTERFACE_ATTRIBUTE
573int __interceptor__setjmp(void *env);
574extern "C" int __interceptor__setjmp(void *env) {
575 CHECK(0);
576 return 0;
577}
578
579extern "C" SANITIZER_INTERFACE_ATTRIBUTE
580int TSAN_INTERCEPTOR_SIGSETJMP(void *env);
581extern "C" int TSAN_INTERCEPTOR_SIGSETJMP(void *env) {
582 CHECK(0);
583 return 0;
584}
585
586#if !SANITIZER_NETBSD
587extern "C" SANITIZER_INTERFACE_ATTRIBUTE
588int __interceptor___sigsetjmp(void *env);
589extern "C" int __interceptor___sigsetjmp(void *env) {
590 CHECK(0);
591 return 0;
592}
593#endif
594
595extern "C" int setjmp_symname(void *env);
596extern "C" int _setjmp(void *env);
597extern "C" int sigsetjmp_symname(void *env);
598#if !SANITIZER_NETBSD
599extern "C" int __sigsetjmp(void *env);
600#endif
601DEFINE_REAL(int, setjmp_symname, void *env)
602DEFINE_REAL(int, _setjmp, void *env)
603DEFINE_REAL(int, sigsetjmp_symname, void *env)
604#if !SANITIZER_NETBSD
605DEFINE_REAL(int, __sigsetjmp, void *env)
606#endif
607#endif // SANITIZER_MAC
608
609#if SANITIZER_NETBSD
610#define longjmp_symname __longjmp14
611#define siglongjmp_symname __siglongjmp14
612#else
613#define longjmp_symname longjmp
614#define siglongjmp_symname siglongjmp
615#endif
616
617TSAN_INTERCEPTOR(void, longjmp_symname, uptr *env, int val) {
618 // Note: if we call REAL(longjmp) in the context of ScopedInterceptor,
619 // bad things will happen. We will jump over ScopedInterceptor dtor and can
620 // leave thr->in_ignored_lib set.
621 {
622 SCOPED_INTERCEPTOR_RAW(longjmp_symname, env, val);
623 }
624 LongJmp(cur_thread(), env);
625 REAL(longjmp_symname)(env, val);
626}
627
628TSAN_INTERCEPTOR(void, siglongjmp_symname, uptr *env, int val) {
629 {
630 SCOPED_INTERCEPTOR_RAW(siglongjmp_symname, env, val);
631 }
632 LongJmp(cur_thread(), env);
633 REAL(siglongjmp_symname)(env, val);
634}
635
636#if SANITIZER_NETBSD
637TSAN_INTERCEPTOR(void, _longjmp, uptr *env, int val) {
638 {
639 SCOPED_INTERCEPTOR_RAW(_longjmp, env, val);
640 }
641 LongJmp(cur_thread(), env);
642 REAL(_longjmp)(env, val);
643}
644#endif
645
646#if !SANITIZER_MAC
647TSAN_INTERCEPTOR(void*, malloc, uptr size) {
648 if (in_symbolizer())
649 return InternalAlloc(size);
650 void *p = 0;
651 {
652 SCOPED_INTERCEPTOR_RAW(malloc, size);
653 p = user_alloc(thr, pc, size);
654 }
655 invoke_malloc_hook(p, size);
656 return p;
657}
658
659TSAN_INTERCEPTOR(void*, __libc_memalign, uptr align, uptr sz) {
660 SCOPED_TSAN_INTERCEPTOR(__libc_memalign, align, sz);
661 return user_memalign(thr, pc, align, sz);
662}
663
664TSAN_INTERCEPTOR(void*, calloc, uptr size, uptr n) {
665 if (in_symbolizer())
666 return InternalCalloc(size, n);
667 void *p = 0;
668 {
669 SCOPED_INTERCEPTOR_RAW(calloc, size, n);
670 p = user_calloc(thr, pc, size, n);
671 }
672 invoke_malloc_hook(p, n * size);
673 return p;
674}
675
676TSAN_INTERCEPTOR(void*, realloc, void *p, uptr size) {
677 if (in_symbolizer())
678 return InternalRealloc(p, size);
679 if (p)
680 invoke_free_hook(p);
681 {
682 SCOPED_INTERCEPTOR_RAW(realloc, p, size);
683 p = user_realloc(thr, pc, p, size);
684 }
685 invoke_malloc_hook(p, size);
686 return p;
687}
688
689TSAN_INTERCEPTOR(void*, reallocarray, void *p, uptr size, uptr n) {
690 if (in_symbolizer())
691 return InternalReallocArray(p, size, n);
692 if (p)
693 invoke_free_hook(p);
694 {
695 SCOPED_INTERCEPTOR_RAW(reallocarray, p, size, n);
696 p = user_reallocarray(thr, pc, p, size, n);
697 }
698 invoke_malloc_hook(p, size);
699 return p;
700}
701
702TSAN_INTERCEPTOR(void, free, void *p) {
703 if (p == 0)
704 return;
705 if (in_symbolizer())
706 return InternalFree(p);
707 invoke_free_hook(p);
708 SCOPED_INTERCEPTOR_RAW(free, p);
709 user_free(thr, pc, p);
710}
711
712TSAN_INTERCEPTOR(void, cfree, void *p) {
713 if (p == 0)
714 return;
715 if (in_symbolizer())
716 return InternalFree(p);
717 invoke_free_hook(p);
718 SCOPED_INTERCEPTOR_RAW(cfree, p);
719 user_free(thr, pc, p);
720}
721
722TSAN_INTERCEPTOR(uptr, malloc_usable_size, void *p) {
723 SCOPED_INTERCEPTOR_RAW(malloc_usable_size, p);
724 return user_alloc_usable_size(p);
725}
726#endif
727
728TSAN_INTERCEPTOR(char *, strcpy, char *dst, const char *src) {
729 SCOPED_TSAN_INTERCEPTOR(strcpy, dst, src);
730 uptr srclen = internal_strlen(src);
731 MemoryAccessRange(thr, pc, (uptr)dst, srclen + 1, true);
732 MemoryAccessRange(thr, pc, (uptr)src, srclen + 1, false);
733 return REAL(strcpy)(dst, src);
734}
735
736TSAN_INTERCEPTOR(char*, strncpy, char *dst, char *src, uptr n) {
737 SCOPED_TSAN_INTERCEPTOR(strncpy, dst, src, n);
738 uptr srclen = internal_strnlen(src, n);
739 MemoryAccessRange(thr, pc, (uptr)dst, n, true);
740 MemoryAccessRange(thr, pc, (uptr)src, min(srclen + 1, n), false);
741 return REAL(strncpy)(dst, src, n);
742}
743
744TSAN_INTERCEPTOR(char*, strdup, const char *str) {
745 SCOPED_TSAN_INTERCEPTOR(strdup, str);
746 // strdup will call malloc, so no instrumentation is required here.
747 return REAL(strdup)(str);
748}
749
750// Zero out addr if it points into shadow memory and was provided as a hint
751// only, i.e., MAP_FIXED is not set.
752static bool fix_mmap_addr(void **addr, long_t sz, int flags) {
753 if (*addr) {
754 if (!IsAppMem((uptr)*addr) || !IsAppMem((uptr)*addr + sz - 1)) {
755 if (flags & MAP_FIXED) {
756 errno = errno_EINVAL;
757 return false;
758 } else {
759 *addr = 0;
760 }
761 }
762 }
763 return true;
764}
765
766template <class Mmap>
767static void *mmap_interceptor(ThreadState *thr, uptr pc, Mmap real_mmap,
768 void *addr, SIZE_T sz, int prot, int flags,
769 int fd, OFF64_T off) {
770 if (!fix_mmap_addr(&addr, sz, flags)) return MAP_FAILED;
771 void *res = real_mmap(addr, sz, prot, flags, fd, off);
772 if (res != MAP_FAILED) {
773 if (fd > 0) FdAccess(thr, pc, fd);
774 MemoryRangeImitateWriteOrResetRange(thr, pc, (uptr)res, sz);
775 }
776 return res;
777}
778
779TSAN_INTERCEPTOR(int, munmap, void *addr, long_t sz) {
780 SCOPED_TSAN_INTERCEPTOR(munmap, addr, sz);
781 UnmapShadow(thr, (uptr)addr, sz);
782 int res = REAL(munmap)(addr, sz);
783 return res;
784}
785
786#if SANITIZER_LINUX
787TSAN_INTERCEPTOR(void*, memalign, uptr align, uptr sz) {
788 SCOPED_INTERCEPTOR_RAW(memalign, align, sz);
789 return user_memalign(thr, pc, align, sz);
790}
791#define TSAN_MAYBE_INTERCEPT_MEMALIGN TSAN_INTERCEPT(memalign)
792#else
793#define TSAN_MAYBE_INTERCEPT_MEMALIGN
794#endif
795
796#if !SANITIZER_MAC
797TSAN_INTERCEPTOR(void*, aligned_alloc, uptr align, uptr sz) {
798 if (in_symbolizer())
799 return InternalAlloc(sz, nullptr, align);
800 SCOPED_INTERCEPTOR_RAW(aligned_alloc, align, sz);
801 return user_aligned_alloc(thr, pc, align, sz);
802}
803
804TSAN_INTERCEPTOR(void*, valloc, uptr sz) {
805 if (in_symbolizer())
806 return InternalAlloc(sz, nullptr, GetPageSizeCached());
807 SCOPED_INTERCEPTOR_RAW(valloc, sz);
808 return user_valloc(thr, pc, sz);
809}
810#endif
811
812#if SANITIZER_LINUX
813TSAN_INTERCEPTOR(void*, pvalloc, uptr sz) {
814 if (in_symbolizer()) {
815 uptr PageSize = GetPageSizeCached();
816 sz = sz ? RoundUpTo(sz, PageSize) : PageSize;
817 return InternalAlloc(sz, nullptr, PageSize);
818 }
819 SCOPED_INTERCEPTOR_RAW(pvalloc, sz);
820 return user_pvalloc(thr, pc, sz);
821}
822#define TSAN_MAYBE_INTERCEPT_PVALLOC TSAN_INTERCEPT(pvalloc)
823#else
824#define TSAN_MAYBE_INTERCEPT_PVALLOC
825#endif
826
827#if !SANITIZER_MAC
828TSAN_INTERCEPTOR(int, posix_memalign, void **memptr, uptr align, uptr sz) {
829 if (in_symbolizer()) {
830 void *p = InternalAlloc(sz, nullptr, align);
831 if (!p)
832 return errno_ENOMEM;
833 *memptr = p;
834 return 0;
835 }
836 SCOPED_INTERCEPTOR_RAW(posix_memalign, memptr, align, sz);
837 return user_posix_memalign(thr, pc, memptr, align, sz);
838}
839#endif
840
841// __cxa_guard_acquire and friends need to be intercepted in a special way -
842// regular interceptors will break statically-linked libstdc++. Linux
843// interceptors are especially defined as weak functions (so that they don't
844// cause link errors when user defines them as well). So they silently
845// auto-disable themselves when such symbol is already present in the binary. If
846// we link libstdc++ statically, it will bring own __cxa_guard_acquire which
847// will silently replace our interceptor. That's why on Linux we simply export
848// these interceptors with INTERFACE_ATTRIBUTE.
849// On OS X, we don't support statically linking, so we just use a regular
850// interceptor.
851#if SANITIZER_MAC
852#define STDCXX_INTERCEPTOR TSAN_INTERCEPTOR
853#else
854#define STDCXX_INTERCEPTOR(rettype, name, ...) \
855 extern "C" rettype INTERFACE_ATTRIBUTE name(__VA_ARGS__)
856#endif
857
858// Used in thread-safe function static initialization.
859STDCXX_INTERCEPTOR(int, __cxa_guard_acquire, atomic_uint32_t *g) {
860 SCOPED_INTERCEPTOR_RAW(__cxa_guard_acquire, g);
861 OnPotentiallyBlockingRegionBegin();
862 auto on_exit = at_scope_exit(&OnPotentiallyBlockingRegionEnd);
863 for (;;) {
864 u32 cmp = atomic_load(g, memory_order_acquire);
865 if (cmp == 0) {
866 if (atomic_compare_exchange_strong(g, &cmp, 1<<16, memory_order_relaxed))
867 return 1;
868 } else if (cmp == 1) {
869 Acquire(thr, pc, (uptr)g);
870 return 0;
871 } else {
872 internal_sched_yield();
873 }
874 }
875}
876
877STDCXX_INTERCEPTOR(void, __cxa_guard_release, atomic_uint32_t *g) {
878 SCOPED_INTERCEPTOR_RAW(__cxa_guard_release, g);
879 Release(thr, pc, (uptr)g);
880 atomic_store(g, 1, memory_order_release);
881}
882
883STDCXX_INTERCEPTOR(void, __cxa_guard_abort, atomic_uint32_t *g) {
884 SCOPED_INTERCEPTOR_RAW(__cxa_guard_abort, g);
885 atomic_store(g, 0, memory_order_relaxed);
886}
887
888namespace __tsan {
889void DestroyThreadState() {
890 ThreadState *thr = cur_thread();
891 Processor *proc = thr->proc();
892 ThreadFinish(thr);
893 ProcUnwire(proc, thr);
894 ProcDestroy(proc);
895 DTLS_Destroy();
896 cur_thread_finalize();
897}
898
899void PlatformCleanUpThreadState(ThreadState *thr) {
900 ThreadSignalContext *sctx = thr->signal_ctx;
901 if (sctx) {
902 thr->signal_ctx = 0;
903 UnmapOrDie(sctx, sizeof(*sctx));
904 }
905}
906} // namespace __tsan
907
908#if !SANITIZER_MAC && !SANITIZER_NETBSD && !SANITIZER_FREEBSD
909static void thread_finalize(void *v) {
910 uptr iter = (uptr)v;
911 if (iter > 1) {
912 if (pthread_setspecific(interceptor_ctx()->finalize_key,
913 (void*)(iter - 1))) {
914 Printf("ThreadSanitizer: failed to set thread key\n");
915 Die();
916 }
917 return;
918 }
919 DestroyThreadState();
920}
921#endif
922
923
924struct ThreadParam {
925 void* (*callback)(void *arg);
926 void *param;
927 atomic_uintptr_t tid;
928};
929
930extern "C" void *__tsan_thread_start_func(void *arg) {
931 ThreadParam *p = (ThreadParam*)arg;
932 void* (*callback)(void *arg) = p->callback;
933 void *param = p->param;
934 int tid = 0;
935 {
936 cur_thread_init();
937 ThreadState *thr = cur_thread();
938 // Thread-local state is not initialized yet.
939 ScopedIgnoreInterceptors ignore;
940#if !SANITIZER_MAC && !SANITIZER_NETBSD && !SANITIZER_FREEBSD
941 ThreadIgnoreBegin(thr, 0);
942 if (pthread_setspecific(interceptor_ctx()->finalize_key,
943 (void *)GetPthreadDestructorIterations())) {
944 Printf("ThreadSanitizer: failed to set thread key\n");
945 Die();
946 }
947 ThreadIgnoreEnd(thr, 0);
948#endif
949 while ((tid = atomic_load(&p->tid, memory_order_acquire)) == 0)
950 internal_sched_yield();
951 Processor *proc = ProcCreate();
952 ProcWire(proc, thr);
953 ThreadStart(thr, tid, GetTid(), ThreadType::Regular);
954 atomic_store(&p->tid, 0, memory_order_release);
955 }
956 void *res = callback(param);
957 // Prevent the callback from being tail called,
958 // it mixes up stack traces.
959 volatile int foo = 42;
960 foo++;
961 return res;
962}
963
964TSAN_INTERCEPTOR(int, pthread_create,
965 void *th, void *attr, void *(*callback)(void*), void * param) {
966 SCOPED_INTERCEPTOR_RAW(pthread_create, th, attr, callback, param);
967
968 MaybeSpawnBackgroundThread();
969
970 if (ctx->after_multithreaded_fork) {
971 if (flags()->die_after_fork) {
972 Report("ThreadSanitizer: starting new threads after multi-threaded "
973 "fork is not supported. Dying (set die_after_fork=0 to override)\n");
974 Die();
975 } else {
976 VPrintf(1, "ThreadSanitizer: starting new threads after multi-threaded "
977 "fork is not supported (pid %d). Continuing because of "
978 "die_after_fork=0, but you are on your own\n", internal_getpid());
979 }
980 }
981 __sanitizer_pthread_attr_t myattr;
982 if (attr == 0) {
983 pthread_attr_init(&myattr);
984 attr = &myattr;
985 }
986 int detached = 0;
987 REAL(pthread_attr_getdetachstate)(attr, &detached);
988 AdjustStackSize(attr);
989
990 ThreadParam p;
991 p.callback = callback;
992 p.param = param;
993 atomic_store(&p.tid, 0, memory_order_relaxed);
994 int res = -1;
995 {
996 // Otherwise we see false positives in pthread stack manipulation.
997 ScopedIgnoreInterceptors ignore;
998 ThreadIgnoreBegin(thr, pc);
999 res = REAL(pthread_create)(th, attr, __tsan_thread_start_func, &p);
1000 ThreadIgnoreEnd(thr, pc);
1001 }
1002 if (res == 0) {
1003 int tid = ThreadCreate(thr, pc, *(uptr*)th, IsStateDetached(detached));
1004 CHECK_NE(tid, 0);
1005 // Synchronization on p.tid serves two purposes:
1006 // 1. ThreadCreate must finish before the new thread starts.
1007 // Otherwise the new thread can call pthread_detach, but the pthread_t
1008 // identifier is not yet registered in ThreadRegistry by ThreadCreate.
1009 // 2. ThreadStart must finish before this thread continues.
1010 // Otherwise, this thread can call pthread_detach and reset thr->sync
1011 // before the new thread got a chance to acquire from it in ThreadStart.
1012 atomic_store(&p.tid, tid, memory_order_release);
1013 while (atomic_load(&p.tid, memory_order_acquire) != 0)
1014 internal_sched_yield();
1015 }
1016 if (attr == &myattr)
1017 pthread_attr_destroy(&myattr);
1018 return res;
1019}
1020
1021TSAN_INTERCEPTOR(int, pthread_join, void *th, void **ret) {
1022 SCOPED_INTERCEPTOR_RAW(pthread_join, th, ret);
1023 int tid = ThreadConsumeTid(thr, pc, (uptr)th);
1024 ThreadIgnoreBegin(thr, pc);
1025 int res = BLOCK_REAL(pthread_join)(th, ret);
1026 ThreadIgnoreEnd(thr, pc);
1027 if (res == 0) {
1028 ThreadJoin(thr, pc, tid);
1029 }
1030 return res;
1031}
1032
1033DEFINE_REAL_PTHREAD_FUNCTIONS
1034
1035TSAN_INTERCEPTOR(int, pthread_detach, void *th) {
1036 SCOPED_INTERCEPTOR_RAW(pthread_detach, th);
1037 int tid = ThreadConsumeTid(thr, pc, (uptr)th);
1038 int res = REAL(pthread_detach)(th);
1039 if (res == 0) {
1040 ThreadDetach(thr, pc, tid);
1041 }
1042 return res;
1043}
1044
1045TSAN_INTERCEPTOR(void, pthread_exit, void *retval) {
1046 {
1047 SCOPED_INTERCEPTOR_RAW(pthread_exit, retval);
1048#if !SANITIZER_MAC && !SANITIZER_ANDROID
1049 CHECK_EQ(thr, &cur_thread_placeholder);
1050#endif
1051 }
1052 REAL(pthread_exit)(retval);
1053}
1054
1055#if SANITIZER_LINUX
1056TSAN_INTERCEPTOR(int, pthread_tryjoin_np, void *th, void **ret) {
1057 SCOPED_INTERCEPTOR_RAW(pthread_tryjoin_np, th, ret);
1058 int tid = ThreadConsumeTid(thr, pc, (uptr)th);
1059 ThreadIgnoreBegin(thr, pc);
1060 int res = REAL(pthread_tryjoin_np)(th, ret);
1061 ThreadIgnoreEnd(thr, pc);
1062 if (res == 0)
1063 ThreadJoin(thr, pc, tid);
1064 else
1065 ThreadNotJoined(thr, pc, tid, (uptr)th);
1066 return res;
1067}
1068
1069TSAN_INTERCEPTOR(int, pthread_timedjoin_np, void *th, void **ret,
1070 const struct timespec *abstime) {
1071 SCOPED_INTERCEPTOR_RAW(pthread_timedjoin_np, th, ret, abstime);
1072 int tid = ThreadConsumeTid(thr, pc, (uptr)th);
1073 ThreadIgnoreBegin(thr, pc);
1074 int res = BLOCK_REAL(pthread_timedjoin_np)(th, ret, abstime);
1075 ThreadIgnoreEnd(thr, pc);
1076 if (res == 0)
1077 ThreadJoin(thr, pc, tid);
1078 else
1079 ThreadNotJoined(thr, pc, tid, (uptr)th);
1080 return res;
1081}
1082#endif
1083
1084// Problem:
1085// NPTL implementation of pthread_cond has 2 versions (2.2.5 and 2.3.2).
1086// pthread_cond_t has different size in the different versions.
1087// If call new REAL functions for old pthread_cond_t, they will corrupt memory
1088// after pthread_cond_t (old cond is smaller).
1089// If we call old REAL functions for new pthread_cond_t, we will lose some
1090// functionality (e.g. old functions do not support waiting against
1091// CLOCK_REALTIME).
1092// Proper handling would require to have 2 versions of interceptors as well.
1093// But this is messy, in particular requires linker scripts when sanitizer
1094// runtime is linked into a shared library.
1095// Instead we assume we don't have dynamic libraries built against old
1096// pthread (2.2.5 is dated by 2002). And provide legacy_pthread_cond flag
1097// that allows to work with old libraries (but this mode does not support
1098// some features, e.g. pthread_condattr_getpshared).
1099static void *init_cond(void *c, bool force = false) {
1100 // sizeof(pthread_cond_t) >= sizeof(uptr) in both versions.
1101 // So we allocate additional memory on the side large enough to hold
1102 // any pthread_cond_t object. Always call new REAL functions, but pass
1103 // the aux object to them.
1104 // Note: the code assumes that PTHREAD_COND_INITIALIZER initializes
1105 // first word of pthread_cond_t to zero.
1106 // It's all relevant only for linux.
1107 if (!common_flags()->legacy_pthread_cond)
1108 return c;
1109 atomic_uintptr_t *p = (atomic_uintptr_t*)c;
1110 uptr cond = atomic_load(p, memory_order_acquire);
1111 if (!force && cond != 0)
1112 return (void*)cond;
1113 void *newcond = WRAP(malloc)(pthread_cond_t_sz);
1114 internal_memset(newcond, 0, pthread_cond_t_sz);
1115 if (atomic_compare_exchange_strong(p, &cond, (uptr)newcond,
1116 memory_order_acq_rel))
1117 return newcond;
1118 WRAP(free)(newcond);
1119 return (void*)cond;
1120}
1121
1122struct CondMutexUnlockCtx {
1123 ScopedInterceptor *si;
1124 ThreadState *thr;
1125 uptr pc;
1126 void *m;
1127};
1128
1129static void cond_mutex_unlock(CondMutexUnlockCtx *arg) {
1130 // pthread_cond_wait interceptor has enabled async signal delivery
1131 // (see BlockingCall below). Disable async signals since we are running
1132 // tsan code. Also ScopedInterceptor and BlockingCall destructors won't run
1133 // since the thread is cancelled, so we have to manually execute them
1134 // (the thread still can run some user code due to pthread_cleanup_push).
1135 ThreadSignalContext *ctx = SigCtx(arg->thr);
1136 CHECK_EQ(atomic_load(&ctx->in_blocking_func, memory_order_relaxed), 1);
1137 atomic_store(&ctx->in_blocking_func, 0, memory_order_relaxed);
1138 MutexPostLock(arg->thr, arg->pc, (uptr)arg->m, MutexFlagDoPreLockOnPostLock);
1139 // Undo BlockingCall ctor effects.
1140 arg->thr->ignore_interceptors--;
1141 arg->si->~ScopedInterceptor();
1142}
1143
1144INTERCEPTOR(int, pthread_cond_init, void *c, void *a) {
1145 void *cond = init_cond(c, true);
1146 SCOPED_TSAN_INTERCEPTOR(pthread_cond_init, cond, a);
1147 MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), true);
1148 return REAL(pthread_cond_init)(cond, a);
1149}
1150
1151static int cond_wait(ThreadState *thr, uptr pc, ScopedInterceptor *si,
1152 int (*fn)(void *c, void *m, void *abstime), void *c,
1153 void *m, void *t) {
1154 MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), false);
1155 MutexUnlock(thr, pc, (uptr)m);
1156 CondMutexUnlockCtx arg = {si, thr, pc, m};
1157 int res = 0;
1158 // This ensures that we handle mutex lock even in case of pthread_cancel.
1159 // See test/tsan/cond_cancel.cpp.
1160 {
1161 // Enable signal delivery while the thread is blocked.
1162 BlockingCall bc(thr);
1163 res = call_pthread_cancel_with_cleanup(
1164 fn, c, m, t, (void (*)(void *arg))cond_mutex_unlock, &arg);
1165 }
1166 if (res == errno_EOWNERDEAD) MutexRepair(thr, pc, (uptr)m);
1167 MutexPostLock(thr, pc, (uptr)m, MutexFlagDoPreLockOnPostLock);
1168 return res;
1169}
1170
1171INTERCEPTOR(int, pthread_cond_wait, void *c, void *m) {
1172 void *cond = init_cond(c);
1173 SCOPED_TSAN_INTERCEPTOR(pthread_cond_wait, cond, m);
1174 return cond_wait(thr, pc, &si, (int (*)(void *c, void *m, void *abstime))REAL(
1175 pthread_cond_wait),
1176 cond, m, 0);
1177}
1178
1179INTERCEPTOR(int, pthread_cond_timedwait, void *c, void *m, void *abstime) {
1180 void *cond = init_cond(c);
1181 SCOPED_TSAN_INTERCEPTOR(pthread_cond_timedwait, cond, m, abstime);
1182 return cond_wait(thr, pc, &si, REAL(pthread_cond_timedwait), cond, m,
1183 abstime);
1184}
1185
1186#if SANITIZER_MAC
1187INTERCEPTOR(int, pthread_cond_timedwait_relative_np, void *c, void *m,
1188 void *reltime) {
1189 void *cond = init_cond(c);
1190 SCOPED_TSAN_INTERCEPTOR(pthread_cond_timedwait_relative_np, cond, m, reltime);
1191 return cond_wait(thr, pc, &si, REAL(pthread_cond_timedwait_relative_np), cond,
1192 m, reltime);
1193}
1194#endif
1195
1196INTERCEPTOR(int, pthread_cond_signal, void *c) {
1197 void *cond = init_cond(c);
1198 SCOPED_TSAN_INTERCEPTOR(pthread_cond_signal, cond);
1199 MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), false);
1200 return REAL(pthread_cond_signal)(cond);
1201}
1202
1203INTERCEPTOR(int, pthread_cond_broadcast, void *c) {
1204 void *cond = init_cond(c);
1205 SCOPED_TSAN_INTERCEPTOR(pthread_cond_broadcast, cond);
1206 MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), false);
1207 return REAL(pthread_cond_broadcast)(cond);
1208}
1209
1210INTERCEPTOR(int, pthread_cond_destroy, void *c) {
1211 void *cond = init_cond(c);
1212 SCOPED_TSAN_INTERCEPTOR(pthread_cond_destroy, cond);
1213 MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), true);
1214 int res = REAL(pthread_cond_destroy)(cond);
1215 if (common_flags()->legacy_pthread_cond) {
1216 // Free our aux cond and zero the pointer to not leave dangling pointers.
1217 WRAP(free)(cond);
1218 atomic_store((atomic_uintptr_t*)c, 0, memory_order_relaxed);
1219 }
1220 return res;
1221}
1222
1223TSAN_INTERCEPTOR(int, pthread_mutex_init, void *m, void *a) {
1224 SCOPED_TSAN_INTERCEPTOR(pthread_mutex_init, m, a);
1225 int res = REAL(pthread_mutex_init)(m, a);
1226 if (res == 0) {
1227 u32 flagz = 0;
1228 if (a) {
1229 int type = 0;
1230 if (REAL(pthread_mutexattr_gettype)(a, &type) == 0)
1231 if (type == PTHREAD_MUTEX_RECURSIVE ||
1232 type == PTHREAD_MUTEX_RECURSIVE_NP)
1233 flagz |= MutexFlagWriteReentrant;
1234 }
1235 MutexCreate(thr, pc, (uptr)m, flagz);
1236 }
1237 return res;
1238}
1239
1240TSAN_INTERCEPTOR(int, pthread_mutex_destroy, void *m) {
1241 SCOPED_TSAN_INTERCEPTOR(pthread_mutex_destroy, m);
1242 int res = REAL(pthread_mutex_destroy)(m);
1243 if (res == 0 || res == errno_EBUSY) {
1244 MutexDestroy(thr, pc, (uptr)m);
1245 }
1246 return res;
1247}
1248
1249TSAN_INTERCEPTOR(int, pthread_mutex_trylock, void *m) {
1250 SCOPED_TSAN_INTERCEPTOR(pthread_mutex_trylock, m);
1251 int res = REAL(pthread_mutex_trylock)(m);
1252 if (res == errno_EOWNERDEAD)
1253 MutexRepair(thr, pc, (uptr)m);
1254 if (res == 0 || res == errno_EOWNERDEAD)
1255 MutexPostLock(thr, pc, (uptr)m, MutexFlagTryLock);
1256 return res;
1257}
1258
1259#if !SANITIZER_MAC
1260TSAN_INTERCEPTOR(int, pthread_mutex_timedlock, void *m, void *abstime) {
1261 SCOPED_TSAN_INTERCEPTOR(pthread_mutex_timedlock, m, abstime);
1262 int res = REAL(pthread_mutex_timedlock)(m, abstime);
1263 if (res == 0) {
1264 MutexPostLock(thr, pc, (uptr)m, MutexFlagTryLock);
1265 }
1266 return res;
1267}
1268#endif
1269
1270#if !SANITIZER_MAC
1271TSAN_INTERCEPTOR(int, pthread_spin_init, void *m, int pshared) {
1272 SCOPED_TSAN_INTERCEPTOR(pthread_spin_init, m, pshared);
1273 int res = REAL(pthread_spin_init)(m, pshared);
1274 if (res == 0) {
1275 MutexCreate(thr, pc, (uptr)m);
1276 }
1277 return res;
1278}
1279
1280TSAN_INTERCEPTOR(int, pthread_spin_destroy, void *m) {
1281 SCOPED_TSAN_INTERCEPTOR(pthread_spin_destroy, m);
1282 int res = REAL(pthread_spin_destroy)(m);
1283 if (res == 0) {
1284 MutexDestroy(thr, pc, (uptr)m);
1285 }
1286 return res;
1287}
1288
1289TSAN_INTERCEPTOR(int, pthread_spin_lock, void *m) {
1290 SCOPED_TSAN_INTERCEPTOR(pthread_spin_lock, m);
1291 MutexPreLock(thr, pc, (uptr)m);
1292 int res = REAL(pthread_spin_lock)(m);
1293 if (res == 0) {
1294 MutexPostLock(thr, pc, (uptr)m);
1295 }
1296 return res;
1297}
1298
1299TSAN_INTERCEPTOR(int, pthread_spin_trylock, void *m) {
1300 SCOPED_TSAN_INTERCEPTOR(pthread_spin_trylock, m);
1301 int res = REAL(pthread_spin_trylock)(m);
1302 if (res == 0) {
1303 MutexPostLock(thr, pc, (uptr)m, MutexFlagTryLock);
1304 }
1305 return res;
1306}
1307
1308TSAN_INTERCEPTOR(int, pthread_spin_unlock, void *m) {
1309 SCOPED_TSAN_INTERCEPTOR(pthread_spin_unlock, m);
1310 MutexUnlock(thr, pc, (uptr)m);
1311 int res = REAL(pthread_spin_unlock)(m);
1312 return res;
1313}
1314#endif
1315
1316TSAN_INTERCEPTOR(int, pthread_rwlock_init, void *m, void *a) {
1317 SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_init, m, a);
1318 int res = REAL(pthread_rwlock_init)(m, a);
1319 if (res == 0) {
1320 MutexCreate(thr, pc, (uptr)m);
1321 }
1322 return res;
1323}
1324
1325TSAN_INTERCEPTOR(int, pthread_rwlock_destroy, void *m) {
1326 SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_destroy, m);
1327 int res = REAL(pthread_rwlock_destroy)(m);
1328 if (res == 0) {
1329 MutexDestroy(thr, pc, (uptr)m);
1330 }
1331 return res;
1332}
1333
1334TSAN_INTERCEPTOR(int, pthread_rwlock_rdlock, void *m) {
1335 SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_rdlock, m);
1336 MutexPreReadLock(thr, pc, (uptr)m);
1337 int res = REAL(pthread_rwlock_rdlock)(m);
1338 if (res == 0) {
1339 MutexPostReadLock(thr, pc, (uptr)m);
1340 }
1341 return res;
1342}
1343
1344TSAN_INTERCEPTOR(int, pthread_rwlock_tryrdlock, void *m) {
1345 SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_tryrdlock, m);
1346 int res = REAL(pthread_rwlock_tryrdlock)(m);
1347 if (res == 0) {
1348 MutexPostReadLock(thr, pc, (uptr)m, MutexFlagTryLock);
1349 }
1350 return res;
1351}
1352
1353#if !SANITIZER_MAC
1354TSAN_INTERCEPTOR(int, pthread_rwlock_timedrdlock, void *m, void *abstime) {
1355 SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_timedrdlock, m, abstime);
1356 int res = REAL(pthread_rwlock_timedrdlock)(m, abstime);
1357 if (res == 0) {
1358 MutexPostReadLock(thr, pc, (uptr)m);
1359 }
1360 return res;
1361}
1362#endif
1363
1364TSAN_INTERCEPTOR(int, pthread_rwlock_wrlock, void *m) {
1365 SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_wrlock, m);
1366 MutexPreLock(thr, pc, (uptr)m);
1367 int res = REAL(pthread_rwlock_wrlock)(m);
1368 if (res == 0) {
1369 MutexPostLock(thr, pc, (uptr)m);
1370 }
1371 return res;
1372}
1373
1374TSAN_INTERCEPTOR(int, pthread_rwlock_trywrlock, void *m) {
1375 SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_trywrlock, m);
1376 int res = REAL(pthread_rwlock_trywrlock)(m);
1377 if (res == 0) {
1378 MutexPostLock(thr, pc, (uptr)m, MutexFlagTryLock);
1379 }
1380 return res;
1381}
1382
1383#if !SANITIZER_MAC
1384TSAN_INTERCEPTOR(int, pthread_rwlock_timedwrlock, void *m, void *abstime) {
1385 SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_timedwrlock, m, abstime);
1386 int res = REAL(pthread_rwlock_timedwrlock)(m, abstime);
1387 if (res == 0) {
1388 MutexPostLock(thr, pc, (uptr)m, MutexFlagTryLock);
1389 }
1390 return res;
1391}
1392#endif
1393
1394TSAN_INTERCEPTOR(int, pthread_rwlock_unlock, void *m) {
1395 SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_unlock, m);
1396 MutexReadOrWriteUnlock(thr, pc, (uptr)m);
1397 int res = REAL(pthread_rwlock_unlock)(m);
1398 return res;
1399}
1400
1401#if !SANITIZER_MAC
1402TSAN_INTERCEPTOR(int, pthread_barrier_init, void *b, void *a, unsigned count) {
1403 SCOPED_TSAN_INTERCEPTOR(pthread_barrier_init, b, a, count);
1404 MemoryWrite(thr, pc, (uptr)b, kSizeLog1);
1405 int res = REAL(pthread_barrier_init)(b, a, count);
1406 return res;
1407}
1408
1409TSAN_INTERCEPTOR(int, pthread_barrier_destroy, void *b) {
1410 SCOPED_TSAN_INTERCEPTOR(pthread_barrier_destroy, b);
1411 MemoryWrite(thr, pc, (uptr)b, kSizeLog1);
1412 int res = REAL(pthread_barrier_destroy)(b);
1413 return res;
1414}
1415
1416TSAN_INTERCEPTOR(int, pthread_barrier_wait, void *b) {
1417 SCOPED_TSAN_INTERCEPTOR(pthread_barrier_wait, b);
1418 Release(thr, pc, (uptr)b);
1419 MemoryRead(thr, pc, (uptr)b, kSizeLog1);
1420 int res = REAL(pthread_barrier_wait)(b);
1421 MemoryRead(thr, pc, (uptr)b, kSizeLog1);
1422 if (res == 0 || res == PTHREAD_BARRIER_SERIAL_THREAD) {
1423 Acquire(thr, pc, (uptr)b);
1424 }
1425 return res;
1426}
1427#endif
1428
1429TSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) {
1430 SCOPED_INTERCEPTOR_RAW(pthread_once, o, f);
1431 if (o == 0 || f == 0)
1432 return errno_EINVAL;
1433 atomic_uint32_t *a;
1434
1435 if (SANITIZER_MAC)
1436 a = static_cast<atomic_uint32_t*>((void *)((char *)o + sizeof(long_t)));
1437 else if (SANITIZER_NETBSD)
1438 a = static_cast<atomic_uint32_t*>
1439 ((void *)((char *)o + __sanitizer::pthread_mutex_t_sz));
1440 else
1441 a = static_cast<atomic_uint32_t*>(o);
1442
1443 u32 v = atomic_load(a, memory_order_acquire);
1444 if (v == 0 && atomic_compare_exchange_strong(a, &v, 1,
1445 memory_order_relaxed)) {
1446 (*f)();
1447 if (!thr->in_ignored_lib)
1448 Release(thr, pc, (uptr)o);
1449 atomic_store(a, 2, memory_order_release);
1450 } else {
1451 while (v != 2) {
1452 internal_sched_yield();
1453 v = atomic_load(a, memory_order_acquire);
1454 }
1455 if (!thr->in_ignored_lib)
1456 Acquire(thr, pc, (uptr)o);
1457 }
1458 return 0;
1459}
1460
1461#if SANITIZER_LINUX && !SANITIZER_ANDROID
1462TSAN_INTERCEPTOR(int, __fxstat, int version, int fd, void *buf) {
1463 SCOPED_TSAN_INTERCEPTOR(__fxstat, version, fd, buf);
1464 if (fd > 0)
1465 FdAccess(thr, pc, fd);
1466 return REAL(__fxstat)(version, fd, buf);
1467}
1468#define TSAN_MAYBE_INTERCEPT___FXSTAT TSAN_INTERCEPT(__fxstat)
1469#else
1470#define TSAN_MAYBE_INTERCEPT___FXSTAT
1471#endif
1472
1473TSAN_INTERCEPTOR(int, fstat, int fd, void *buf) {
1474#if SANITIZER_FREEBSD || SANITIZER_MAC || SANITIZER_ANDROID || SANITIZER_NETBSD
1475 SCOPED_TSAN_INTERCEPTOR(fstat, fd, buf);
1476 if (fd > 0)
1477 FdAccess(thr, pc, fd);
1478 return REAL(fstat)(fd, buf);
1479#else
1480 SCOPED_TSAN_INTERCEPTOR(__fxstat, 0, fd, buf);
1481 if (fd > 0)
1482 FdAccess(thr, pc, fd);
1483 return REAL(__fxstat)(0, fd, buf);
1484#endif
1485}
1486
1487#if SANITIZER_LINUX && !SANITIZER_ANDROID
1488TSAN_INTERCEPTOR(int, __fxstat64, int version, int fd, void *buf) {
1489 SCOPED_TSAN_INTERCEPTOR(__fxstat64, version, fd, buf);
1490 if (fd > 0)
1491 FdAccess(thr, pc, fd);
1492 return REAL(__fxstat64)(version, fd, buf);
1493}
1494#define TSAN_MAYBE_INTERCEPT___FXSTAT64 TSAN_INTERCEPT(__fxstat64)
1495#else
1496#define TSAN_MAYBE_INTERCEPT___FXSTAT64
1497#endif
1498
1499#if SANITIZER_LINUX && !SANITIZER_ANDROID
1500TSAN_INTERCEPTOR(int, fstat64, int fd, void *buf) {
1501 SCOPED_TSAN_INTERCEPTOR(__fxstat64, 0, fd, buf);
1502 if (fd > 0)
1503 FdAccess(thr, pc, fd);
1504 return REAL(__fxstat64)(0, fd, buf);
1505}
1506#define TSAN_MAYBE_INTERCEPT_FSTAT64 TSAN_INTERCEPT(fstat64)
1507#else
1508#define TSAN_MAYBE_INTERCEPT_FSTAT64
1509#endif
1510
1511TSAN_INTERCEPTOR(int, open, const char *name, int flags, int mode) {
1512 SCOPED_TSAN_INTERCEPTOR(open, name, flags, mode);
1513 READ_STRING(thr, pc, name, 0);
1514 int fd = REAL(open)(name, flags, mode);
1515 if (fd >= 0)
1516 FdFileCreate(thr, pc, fd);
1517 return fd;
1518}
1519
1520#if SANITIZER_LINUX
1521TSAN_INTERCEPTOR(int, open64, const char *name, int flags, int mode) {
1522 SCOPED_TSAN_INTERCEPTOR(open64, name, flags, mode);
1523 READ_STRING(thr, pc, name, 0);
1524 int fd = REAL(open64)(name, flags, mode);
1525 if (fd >= 0)
1526 FdFileCreate(thr, pc, fd);
1527 return fd;
1528}
1529#define TSAN_MAYBE_INTERCEPT_OPEN64 TSAN_INTERCEPT(open64)
1530#else
1531#define TSAN_MAYBE_INTERCEPT_OPEN64
1532#endif
1533
1534TSAN_INTERCEPTOR(int, creat, const char *name, int mode) {
1535 SCOPED_TSAN_INTERCEPTOR(creat, name, mode);
1536 READ_STRING(thr, pc, name, 0);
1537 int fd = REAL(creat)(name, mode);
1538 if (fd >= 0)
1539 FdFileCreate(thr, pc, fd);
1540 return fd;
1541}
1542
1543#if SANITIZER_LINUX
1544TSAN_INTERCEPTOR(int, creat64, const char *name, int mode) {
1545 SCOPED_TSAN_INTERCEPTOR(creat64, name, mode);
1546 READ_STRING(thr, pc, name, 0);
1547 int fd = REAL(creat64)(name, mode);
1548 if (fd >= 0)
1549 FdFileCreate(thr, pc, fd);
1550 return fd;
1551}
1552#define TSAN_MAYBE_INTERCEPT_CREAT64 TSAN_INTERCEPT(creat64)
1553#else
1554#define TSAN_MAYBE_INTERCEPT_CREAT64
1555#endif
1556
1557TSAN_INTERCEPTOR(int, dup, int oldfd) {
1558 SCOPED_TSAN_INTERCEPTOR(dup, oldfd);
1559 int newfd = REAL(dup)(oldfd);
1560 if (oldfd >= 0 && newfd >= 0 && newfd != oldfd)
1561 FdDup(thr, pc, oldfd, newfd, true);
1562 return newfd;
1563}
1564
1565TSAN_INTERCEPTOR(int, dup2, int oldfd, int newfd) {
1566 SCOPED_TSAN_INTERCEPTOR(dup2, oldfd, newfd);
1567 int newfd2 = REAL(dup2)(oldfd, newfd);
1568 if (oldfd >= 0 && newfd2 >= 0 && newfd2 != oldfd)
1569 FdDup(thr, pc, oldfd, newfd2, false);
1570 return newfd2;
1571}
1572
1573#if !SANITIZER_MAC
1574TSAN_INTERCEPTOR(int, dup3, int oldfd, int newfd, int flags) {
1575 SCOPED_TSAN_INTERCEPTOR(dup3, oldfd, newfd, flags);
1576 int newfd2 = REAL(dup3)(oldfd, newfd, flags);
1577 if (oldfd >= 0 && newfd2 >= 0 && newfd2 != oldfd)
1578 FdDup(thr, pc, oldfd, newfd2, false);
1579 return newfd2;
1580}
1581#endif
1582
1583#if SANITIZER_LINUX
1584TSAN_INTERCEPTOR(int, eventfd, unsigned initval, int flags) {
1585 SCOPED_TSAN_INTERCEPTOR(eventfd, initval, flags);
1586 int fd = REAL(eventfd)(initval, flags);
1587 if (fd >= 0)
1588 FdEventCreate(thr, pc, fd);
1589 return fd;
1590}
1591#define TSAN_MAYBE_INTERCEPT_EVENTFD TSAN_INTERCEPT(eventfd)
1592#else
1593#define TSAN_MAYBE_INTERCEPT_EVENTFD
1594#endif
1595
1596#if SANITIZER_LINUX
1597TSAN_INTERCEPTOR(int, signalfd, int fd, void *mask, int flags) {
1598 SCOPED_TSAN_INTERCEPTOR(signalfd, fd, mask, flags);
1599 if (fd >= 0)
1600 FdClose(thr, pc, fd);
1601 fd = REAL(signalfd)(fd, mask, flags);
1602 if (fd >= 0)
1603 FdSignalCreate(thr, pc, fd);
1604 return fd;
1605}
1606#define TSAN_MAYBE_INTERCEPT_SIGNALFD TSAN_INTERCEPT(signalfd)
1607#else
1608#define TSAN_MAYBE_INTERCEPT_SIGNALFD
1609#endif
1610
1611#if SANITIZER_LINUX
1612TSAN_INTERCEPTOR(int, inotify_init, int fake) {
1613 SCOPED_TSAN_INTERCEPTOR(inotify_init, fake);
1614 int fd = REAL(inotify_init)(fake);
1615 if (fd >= 0)
1616 FdInotifyCreate(thr, pc, fd);
1617 return fd;
1618}
1619#define TSAN_MAYBE_INTERCEPT_INOTIFY_INIT TSAN_INTERCEPT(inotify_init)
1620#else
1621#define TSAN_MAYBE_INTERCEPT_INOTIFY_INIT
1622#endif
1623
1624#if SANITIZER_LINUX
1625TSAN_INTERCEPTOR(int, inotify_init1, int flags) {
1626 SCOPED_TSAN_INTERCEPTOR(inotify_init1, flags);
1627 int fd = REAL(inotify_init1)(flags);
1628 if (fd >= 0)
1629 FdInotifyCreate(thr, pc, fd);
1630 return fd;
1631}
1632#define TSAN_MAYBE_INTERCEPT_INOTIFY_INIT1 TSAN_INTERCEPT(inotify_init1)
1633#else
1634#define TSAN_MAYBE_INTERCEPT_INOTIFY_INIT1
1635#endif
1636
1637TSAN_INTERCEPTOR(int, socket, int domain, int type, int protocol) {
1638 SCOPED_TSAN_INTERCEPTOR(socket, domain, type, protocol);
1639 int fd = REAL(socket)(domain, type, protocol);
1640 if (fd >= 0)
1641 FdSocketCreate(thr, pc, fd);
1642 return fd;
1643}
1644
1645TSAN_INTERCEPTOR(int, socketpair, int domain, int type, int protocol, int *fd) {
1646 SCOPED_TSAN_INTERCEPTOR(socketpair, domain, type, protocol, fd);
1647 int res = REAL(socketpair)(domain, type, protocol, fd);
1648 if (res == 0 && fd[0] >= 0 && fd[1] >= 0)
1649 FdPipeCreate(thr, pc, fd[0], fd[1]);
1650 return res;
1651}
1652
1653TSAN_INTERCEPTOR(int, connect, int fd, void *addr, unsigned addrlen) {
1654 SCOPED_TSAN_INTERCEPTOR(connect, fd, addr, addrlen);
1655 FdSocketConnecting(thr, pc, fd);
1656 int res = REAL(connect)(fd, addr, addrlen);
1657 if (res == 0 && fd >= 0)
1658 FdSocketConnect(thr, pc, fd);
1659 return res;
1660}
1661
1662TSAN_INTERCEPTOR(int, bind, int fd, void *addr, unsigned addrlen) {
1663 SCOPED_TSAN_INTERCEPTOR(bind, fd, addr, addrlen);
1664 int res = REAL(bind)(fd, addr, addrlen);
1665 if (fd > 0 && res == 0)
1666 FdAccess(thr, pc, fd);
1667 return res;
1668}
1669
1670TSAN_INTERCEPTOR(int, listen, int fd, int backlog) {
1671 SCOPED_TSAN_INTERCEPTOR(listen, fd, backlog);
1672 int res = REAL(listen)(fd, backlog);
1673 if (fd > 0 && res == 0)
1674 FdAccess(thr, pc, fd);
1675 return res;
1676}
1677
1678TSAN_INTERCEPTOR(int, close, int fd) {
1679 SCOPED_TSAN_INTERCEPTOR(close, fd);
1680 if (fd >= 0)
1681 FdClose(thr, pc, fd);
1682 return REAL(close)(fd);
1683}
1684
1685#if SANITIZER_LINUX
1686TSAN_INTERCEPTOR(int, __close, int fd) {
1687 SCOPED_TSAN_INTERCEPTOR(__close, fd);
1688 if (fd >= 0)
1689 FdClose(thr, pc, fd);
1690 return REAL(__close)(fd);
1691}
1692#define TSAN_MAYBE_INTERCEPT___CLOSE TSAN_INTERCEPT(__close)
1693#else
1694#define TSAN_MAYBE_INTERCEPT___CLOSE
1695#endif
1696
1697// glibc guts
1698#if SANITIZER_LINUX && !SANITIZER_ANDROID
1699TSAN_INTERCEPTOR(void, __res_iclose, void *state, bool free_addr) {
1700 SCOPED_TSAN_INTERCEPTOR(__res_iclose, state, free_addr);
1701 int fds[64];
1702 int cnt = ExtractResolvFDs(state, fds, ARRAY_SIZE(fds));
1703 for (int i = 0; i < cnt; i++) {
1704 if (fds[i] > 0)
1705 FdClose(thr, pc, fds[i]);
1706 }
1707 REAL(__res_iclose)(state, free_addr);
1708}
1709#define TSAN_MAYBE_INTERCEPT___RES_ICLOSE TSAN_INTERCEPT(__res_iclose)
1710#else
1711#define TSAN_MAYBE_INTERCEPT___RES_ICLOSE
1712#endif
1713
1714TSAN_INTERCEPTOR(int, pipe, int *pipefd) {
1715 SCOPED_TSAN_INTERCEPTOR(pipe, pipefd);
1716 int res = REAL(pipe)(pipefd);
1717 if (res == 0 && pipefd[0] >= 0 && pipefd[1] >= 0)
1718 FdPipeCreate(thr, pc, pipefd[0], pipefd[1]);
1719 return res;
1720}
1721
1722#if !SANITIZER_MAC
1723TSAN_INTERCEPTOR(int, pipe2, int *pipefd, int flags) {
1724 SCOPED_TSAN_INTERCEPTOR(pipe2, pipefd, flags);
1725 int res = REAL(pipe2)(pipefd, flags);
1726 if (res == 0 && pipefd[0] >= 0 && pipefd[1] >= 0)
1727 FdPipeCreate(thr, pc, pipefd[0], pipefd[1]);
1728 return res;
1729}
1730#endif
1731
1732TSAN_INTERCEPTOR(int, unlink, char *path) {
1733 SCOPED_TSAN_INTERCEPTOR(unlink, path);
1734 Release(thr, pc, File2addr(path));
1735 int res = REAL(unlink)(path);
1736 return res;
1737}
1738
1739TSAN_INTERCEPTOR(void*, tmpfile, int fake) {
1740 SCOPED_TSAN_INTERCEPTOR(tmpfile, fake);
1741 void *res = REAL(tmpfile)(fake);
1742 if (res) {
1743 int fd = fileno_unlocked(res);
1744 if (fd >= 0)
1745 FdFileCreate(thr, pc, fd);
1746 }
1747 return res;
1748}
1749
1750#if SANITIZER_LINUX
1751TSAN_INTERCEPTOR(void*, tmpfile64, int fake) {
1752 SCOPED_TSAN_INTERCEPTOR(tmpfile64, fake);
1753 void *res = REAL(tmpfile64)(fake);
1754 if (res) {
1755 int fd = fileno_unlocked(res);
1756 if (fd >= 0)
1757 FdFileCreate(thr, pc, fd);
1758 }
1759 return res;
1760}
1761#define TSAN_MAYBE_INTERCEPT_TMPFILE64 TSAN_INTERCEPT(tmpfile64)
1762#else
1763#define TSAN_MAYBE_INTERCEPT_TMPFILE64
1764#endif
1765
1766static void FlushStreams() {
1767 // Flushing all the streams here may freeze the process if a child thread is
1768 // performing file stream operations at the same time.
1769 REAL(fflush)(stdout);
1770 REAL(fflush)(stderr);
1771}
1772
1773TSAN_INTERCEPTOR(void, abort, int fake) {
1774 SCOPED_TSAN_INTERCEPTOR(abort, fake);
1775 FlushStreams();
1776 REAL(abort)(fake);
1777}
1778
1779TSAN_INTERCEPTOR(int, rmdir, char *path) {
1780 SCOPED_TSAN_INTERCEPTOR(rmdir, path);
1781 Release(thr, pc, Dir2addr(path));
1782 int res = REAL(rmdir)(path);
1783 return res;
1784}
1785
1786TSAN_INTERCEPTOR(int, closedir, void *dirp) {
1787 SCOPED_TSAN_INTERCEPTOR(closedir, dirp);
1788 if (dirp) {
1789 int fd = dirfd(dirp);
1790 FdClose(thr, pc, fd);
1791 }
1792 return REAL(closedir)(dirp);
1793}
1794
1795#if SANITIZER_LINUX
1796TSAN_INTERCEPTOR(int, epoll_create, int size) {
1797 SCOPED_TSAN_INTERCEPTOR(epoll_create, size);
1798 int fd = REAL(epoll_create)(size);
1799 if (fd >= 0)
1800 FdPollCreate(thr, pc, fd);
1801 return fd;
1802}
1803
1804TSAN_INTERCEPTOR(int, epoll_create1, int flags) {
1805 SCOPED_TSAN_INTERCEPTOR(epoll_create1, flags);
1806 int fd = REAL(epoll_create1)(flags);
1807 if (fd >= 0)
1808 FdPollCreate(thr, pc, fd);
1809 return fd;
1810}
1811
1812TSAN_INTERCEPTOR(int, epoll_ctl, int epfd, int op, int fd, void *ev) {
1813 SCOPED_TSAN_INTERCEPTOR(epoll_ctl, epfd, op, fd, ev);
1814 if (epfd >= 0)
1815 FdAccess(thr, pc, epfd);
1816 if (epfd >= 0 && fd >= 0)
1817 FdAccess(thr, pc, fd);
1818 if (op == EPOLL_CTL_ADD && epfd >= 0)
1819 FdRelease(thr, pc, epfd);
1820 int res = REAL(epoll_ctl)(epfd, op, fd, ev);
1821 return res;
1822}
1823
1824TSAN_INTERCEPTOR(int, epoll_wait, int epfd, void *ev, int cnt, int timeout) {
1825 SCOPED_TSAN_INTERCEPTOR(epoll_wait, epfd, ev, cnt, timeout);
1826 if (epfd >= 0)
1827 FdAccess(thr, pc, epfd);
1828 int res = BLOCK_REAL(epoll_wait)(epfd, ev, cnt, timeout);
1829 if (res > 0 && epfd >= 0)
1830 FdAcquire(thr, pc, epfd);
1831 return res;
1832}
1833
1834TSAN_INTERCEPTOR(int, epoll_pwait, int epfd, void *ev, int cnt, int timeout,
1835 void *sigmask) {
1836 SCOPED_TSAN_INTERCEPTOR(epoll_pwait, epfd, ev, cnt, timeout, sigmask);
1837 if (epfd >= 0)
1838 FdAccess(thr, pc, epfd);
1839 int res = BLOCK_REAL(epoll_pwait)(epfd, ev, cnt, timeout, sigmask);
1840 if (res > 0 && epfd >= 0)
1841 FdAcquire(thr, pc, epfd);
1842 return res;
1843}
1844
1845#define TSAN_MAYBE_INTERCEPT_EPOLL \
1846 TSAN_INTERCEPT(epoll_create); \
1847 TSAN_INTERCEPT(epoll_create1); \
1848 TSAN_INTERCEPT(epoll_ctl); \
1849 TSAN_INTERCEPT(epoll_wait); \
1850 TSAN_INTERCEPT(epoll_pwait)
1851#else
1852#define TSAN_MAYBE_INTERCEPT_EPOLL
1853#endif
1854
1855// The following functions are intercepted merely to process pending signals.
1856// If program blocks signal X, we must deliver the signal before the function
1857// returns. Similarly, if program unblocks a signal (or returns from sigsuspend)
1858// it's better to deliver the signal straight away.
1859TSAN_INTERCEPTOR(int, sigsuspend, const __sanitizer_sigset_t *mask) {
1860 SCOPED_TSAN_INTERCEPTOR(sigsuspend, mask);
1861 return REAL(sigsuspend)(mask);
1862}
1863
1864TSAN_INTERCEPTOR(int, sigblock, int mask) {
1865 SCOPED_TSAN_INTERCEPTOR(sigblock, mask);
1866 return REAL(sigblock)(mask);
1867}
1868
1869TSAN_INTERCEPTOR(int, sigsetmask, int mask) {
1870 SCOPED_TSAN_INTERCEPTOR(sigsetmask, mask);
1871 return REAL(sigsetmask)(mask);
1872}
1873
1874TSAN_INTERCEPTOR(int, pthread_sigmask, int how, const __sanitizer_sigset_t *set,
1875 __sanitizer_sigset_t *oldset) {
1876 SCOPED_TSAN_INTERCEPTOR(pthread_sigmask, how, set, oldset);
1877 return REAL(pthread_sigmask)(how, set, oldset);
1878}
1879
1880namespace __tsan {
1881
1882static void CallUserSignalHandler(ThreadState *thr, bool sync, bool acquire,
1883 bool sigact, int sig,
1884 __sanitizer_siginfo *info, void *uctx) {
1885 __sanitizer_sigaction *sigactions = interceptor_ctx()->sigactions;
1886 if (acquire)
1887 Acquire(thr, 0, (uptr)&sigactions[sig]);
1888 // Signals are generally asynchronous, so if we receive a signals when
1889 // ignores are enabled we should disable ignores. This is critical for sync
1890 // and interceptors, because otherwise we can miss syncronization and report
1891 // false races.
1892 int ignore_reads_and_writes = thr->ignore_reads_and_writes;
1893 int ignore_interceptors = thr->ignore_interceptors;
1894 int ignore_sync = thr->ignore_sync;
1895 if (!ctx->after_multithreaded_fork) {
1896 thr->ignore_reads_and_writes = 0;
1897 thr->fast_state.ClearIgnoreBit();
1898 thr->ignore_interceptors = 0;
1899 thr->ignore_sync = 0;
1900 }
1901 // Ensure that the handler does not spoil errno.
1902 const int saved_errno = errno;
1903 errno = 99;
1904 // This code races with sigaction. Be careful to not read sa_sigaction twice.
1905 // Also need to remember pc for reporting before the call,
1906 // because the handler can reset it.
1907 volatile uptr pc =
1908 sigact ? (uptr)sigactions[sig].sigaction : (uptr)sigactions[sig].handler;
1909 if (pc != sig_dfl && pc != sig_ign) {
1910 if (sigact)
1911 ((__sanitizer_sigactionhandler_ptr)pc)(sig, info, uctx);
1912 else
1913 ((__sanitizer_sighandler_ptr)pc)(sig);
1914 }
1915 if (!ctx->after_multithreaded_fork) {
1916 thr->ignore_reads_and_writes = ignore_reads_and_writes;
1917 if (ignore_reads_and_writes)
1918 thr->fast_state.SetIgnoreBit();
1919 thr->ignore_interceptors = ignore_interceptors;
1920 thr->ignore_sync = ignore_sync;
1921 }
1922 // We do not detect errno spoiling for SIGTERM,
1923 // because some SIGTERM handlers do spoil errno but reraise SIGTERM,
1924 // tsan reports false positive in such case.
1925 // It's difficult to properly detect this situation (reraise),
1926 // because in async signal processing case (when handler is called directly
1927 // from rtl_generic_sighandler) we have not yet received the reraised
1928 // signal; and it looks too fragile to intercept all ways to reraise a signal.
1929 if (flags()->report_bugs && !sync && sig != SIGTERM && errno != 99) {
1930 VarSizeStackTrace stack;
1931 // StackTrace::GetNestInstructionPc(pc) is used because return address is
1932 // expected, OutputReport() will undo this.
1933 ObtainCurrentStack(thr, StackTrace::GetNextInstructionPc(pc), &stack);
1934 ThreadRegistryLock l(ctx->thread_registry);
1935 ScopedReport rep(ReportTypeErrnoInSignal);
1936 if (!IsFiredSuppression(ctx, ReportTypeErrnoInSignal, stack)) {
1937 rep.AddStack(stack, true);
1938 OutputReport(thr, rep);
1939 }
1940 }
1941 errno = saved_errno;
1942}
1943
1944void ProcessPendingSignals(ThreadState *thr) {
1945 ThreadSignalContext *sctx = SigCtx(thr);
1946 if (sctx == 0 ||
1947 atomic_load(&sctx->have_pending_signals, memory_order_relaxed) == 0)
1948 return;
1949 atomic_store(&sctx->have_pending_signals, 0, memory_order_relaxed);
1950 atomic_fetch_add(&thr->in_signal_handler, 1, memory_order_relaxed);
1951 internal_sigfillset(&sctx->emptyset);
1952 int res = REAL(pthread_sigmask)(SIG_SETMASK, &sctx->emptyset, &sctx->oldset);
1953 CHECK_EQ(res, 0);
1954 for (int sig = 0; sig < kSigCount; sig++) {
1955 SignalDesc *signal = &sctx->pending_signals[sig];
1956 if (signal->armed) {
1957 signal->armed = false;
1958 CallUserSignalHandler(thr, false, true, signal->sigaction, sig,
1959 &signal->siginfo, &signal->ctx);
1960 }
1961 }
1962 res = REAL(pthread_sigmask)(SIG_SETMASK, &sctx->oldset, 0);
1963 CHECK_EQ(res, 0);
1964 atomic_fetch_add(&thr->in_signal_handler, -1, memory_order_relaxed);
1965}
1966
1967} // namespace __tsan
1968
1969static bool is_sync_signal(ThreadSignalContext *sctx, int sig) {
1970 return sig == SIGSEGV || sig == SIGBUS || sig == SIGILL || sig == SIGTRAP ||
1971 sig == SIGABRT || sig == SIGFPE || sig == SIGPIPE || sig == SIGSYS ||
1972 // If we are sending signal to ourselves, we must process it now.
1973 (sctx && sig == sctx->int_signal_send);
1974}
1975
1976void ALWAYS_INLINE rtl_generic_sighandler(bool sigact, int sig,
1977 __sanitizer_siginfo *info,
1978 void *ctx) {
1979 cur_thread_init();
1980 ThreadState *thr = cur_thread();
1981 ThreadSignalContext *sctx = SigCtx(thr);
1982 if (sig < 0 || sig >= kSigCount) {
1983 VPrintf(1, "ThreadSanitizer: ignoring signal %d\n", sig);
1984 return;
1985 }
1986 // Don't mess with synchronous signals.
1987 const bool sync = is_sync_signal(sctx, sig);
1988 if (sync ||
1989 // If we are in blocking function, we can safely process it now
1990 // (but check if we are in a recursive interceptor,
1991 // i.e. pthread_join()->munmap()).
1992 (sctx && atomic_load(&sctx->in_blocking_func, memory_order_relaxed))) {
1993 atomic_fetch_add(&thr->in_signal_handler, 1, memory_order_relaxed);
1994 if (sctx && atomic_load(&sctx->in_blocking_func, memory_order_relaxed)) {
1995 atomic_store(&sctx->in_blocking_func, 0, memory_order_relaxed);
1996 CallUserSignalHandler(thr, sync, true, sigact, sig, info, ctx);
1997 atomic_store(&sctx->in_blocking_func, 1, memory_order_relaxed);
1998 } else {
1999 // Be very conservative with when we do acquire in this case.
2000 // It's unsafe to do acquire in async handlers, because ThreadState
2001 // can be in inconsistent state.
2002 // SIGSYS looks relatively safe -- it's synchronous and can actually
2003 // need some global state.
2004 bool acq = (sig == SIGSYS);
2005 CallUserSignalHandler(thr, sync, acq, sigact, sig, info, ctx);
2006 }
2007 atomic_fetch_add(&thr->in_signal_handler, -1, memory_order_relaxed);
2008 return;
2009 }
2010
2011 if (sctx == 0)
2012 return;
2013 SignalDesc *signal = &sctx->pending_signals[sig];
2014 if (signal->armed == false) {
2015 signal->armed = true;
2016 signal->sigaction = sigact;
2017 if (info)
2018 internal_memcpy(&signal->siginfo, info, sizeof(*info));
2019 if (ctx)
2020 internal_memcpy(&signal->ctx, ctx, sizeof(signal->ctx));
2021 atomic_store(&sctx->have_pending_signals, 1, memory_order_relaxed);
2022 }
2023}
2024
2025static void rtl_sighandler(int sig) {
2026 rtl_generic_sighandler(false, sig, 0, 0);
2027}
2028
2029static void rtl_sigaction(int sig, __sanitizer_siginfo *info, void *ctx) {
2030 rtl_generic_sighandler(true, sig, info, ctx);
2031}
2032
2033TSAN_INTERCEPTOR(int, raise, int sig) {
2034 SCOPED_TSAN_INTERCEPTOR(raise, sig);
2035 ThreadSignalContext *sctx = SigCtx(thr);
2036 CHECK_NE(sctx, 0);
2037 int prev = sctx->int_signal_send;
2038 sctx->int_signal_send = sig;
2039 int res = REAL(raise)(sig);
2040 CHECK_EQ(sctx->int_signal_send, sig);
2041 sctx->int_signal_send = prev;
2042 return res;
2043}
2044
2045TSAN_INTERCEPTOR(int, kill, int pid, int sig) {
2046 SCOPED_TSAN_INTERCEPTOR(kill, pid, sig);
2047 ThreadSignalContext *sctx = SigCtx(thr);
2048 CHECK_NE(sctx, 0);
2049 int prev = sctx->int_signal_send;
2050 if (pid == (int)internal_getpid()) {
2051 sctx->int_signal_send = sig;
2052 }
2053 int res = REAL(kill)(pid, sig);
2054 if (pid == (int)internal_getpid()) {
2055 CHECK_EQ(sctx->int_signal_send, sig);
2056 sctx->int_signal_send = prev;
2057 }
2058 return res;
2059}
2060
2061TSAN_INTERCEPTOR(int, pthread_kill, void *tid, int sig) {
2062 SCOPED_TSAN_INTERCEPTOR(pthread_kill, tid, sig);
2063 ThreadSignalContext *sctx = SigCtx(thr);
2064 CHECK_NE(sctx, 0);
2065 int prev = sctx->int_signal_send;
2066 if (tid == pthread_self()) {
2067 sctx->int_signal_send = sig;
2068 }
2069 int res = REAL(pthread_kill)(tid, sig);
2070 if (tid == pthread_self()) {
2071 CHECK_EQ(sctx->int_signal_send, sig);
2072 sctx->int_signal_send = prev;
2073 }
2074 return res;
2075}
2076
2077TSAN_INTERCEPTOR(int, gettimeofday, void *tv, void *tz) {
2078 SCOPED_TSAN_INTERCEPTOR(gettimeofday, tv, tz);
2079 // It's intercepted merely to process pending signals.
2080 return REAL(gettimeofday)(tv, tz);
2081}
2082
2083TSAN_INTERCEPTOR(int, getaddrinfo, void *node, void *service,
2084 void *hints, void *rv) {
2085 SCOPED_TSAN_INTERCEPTOR(getaddrinfo, node, service, hints, rv);
2086 // We miss atomic synchronization in getaddrinfo,
2087 // and can report false race between malloc and free
2088 // inside of getaddrinfo. So ignore memory accesses.
2089 ThreadIgnoreBegin(thr, pc);
2090 int res = REAL(getaddrinfo)(node, service, hints, rv);
2091 ThreadIgnoreEnd(thr, pc);
2092 return res;
2093}
2094
2095TSAN_INTERCEPTOR(int, fork, int fake) {
2096 if (in_symbolizer())
2097 return REAL(fork)(fake);
2098 SCOPED_INTERCEPTOR_RAW(fork, fake);
2099 ForkBefore(thr, pc);
2100 int pid;
2101 {
2102 // On OS X, REAL(fork) can call intercepted functions (OSSpinLockLock), and
2103 // we'll assert in CheckNoLocks() unless we ignore interceptors.
2104 ScopedIgnoreInterceptors ignore;
2105 pid = REAL(fork)(fake);
2106 }
2107 if (pid == 0) {
2108 // child
2109 ForkChildAfter(thr, pc);
2110 FdOnFork(thr, pc);
2111 } else if (pid > 0) {
2112 // parent
2113 ForkParentAfter(thr, pc);
2114 } else {
2115 // error
2116 ForkParentAfter(thr, pc);
2117 }
2118 return pid;
2119}
2120
2121TSAN_INTERCEPTOR(int, vfork, int fake) {
2122 // Some programs (e.g. openjdk) call close for all file descriptors
2123 // in the child process. Under tsan it leads to false positives, because
2124 // address space is shared, so the parent process also thinks that
2125 // the descriptors are closed (while they are actually not).
2126 // This leads to false positives due to missed synchronization.
2127 // Strictly saying this is undefined behavior, because vfork child is not
2128 // allowed to call any functions other than exec/exit. But this is what
2129 // openjdk does, so we want to handle it.
2130 // We could disable interceptors in the child process. But it's not possible
2131 // to simply intercept and wrap vfork, because vfork child is not allowed
2132 // to return from the function that calls vfork, and that's exactly what
2133 // we would do. So this would require some assembly trickery as well.
2134 // Instead we simply turn vfork into fork.
2135 return WRAP(fork)(fake);
2136}
2137
2138#if !SANITIZER_MAC && !SANITIZER_ANDROID
2139typedef int (*dl_iterate_phdr_cb_t)(__sanitizer_dl_phdr_info *info, SIZE_T size,
2140 void *data);
2141struct dl_iterate_phdr_data {
2142 ThreadState *thr;
2143 uptr pc;
2144 dl_iterate_phdr_cb_t cb;
2145 void *data;
2146};
2147
2148static bool IsAppNotRodata(uptr addr) {
2149 return IsAppMem(addr) && *(u64*)MemToShadow(addr) != kShadowRodata;
2150}
2151
2152static int dl_iterate_phdr_cb(__sanitizer_dl_phdr_info *info, SIZE_T size,
2153 void *data) {
2154 dl_iterate_phdr_data *cbdata = (dl_iterate_phdr_data *)data;
2155 // dlopen/dlclose allocate/free dynamic-linker-internal memory, which is later
2156 // accessible in dl_iterate_phdr callback. But we don't see synchronization
2157 // inside of dynamic linker, so we "unpoison" it here in order to not
2158 // produce false reports. Ignoring malloc/free in dlopen/dlclose is not enough
2159 // because some libc functions call __libc_dlopen.
2160 if (info && IsAppNotRodata((uptr)info->dlpi_name))
2161 MemoryResetRange(cbdata->thr, cbdata->pc, (uptr)info->dlpi_name,
2162 internal_strlen(info->dlpi_name));
2163 int res = cbdata->cb(info, size, cbdata->data);
2164 // Perform the check one more time in case info->dlpi_name was overwritten
2165 // by user callback.
2166 if (info && IsAppNotRodata((uptr)info->dlpi_name))
2167 MemoryResetRange(cbdata->thr, cbdata->pc, (uptr)info->dlpi_name,
2168 internal_strlen(info->dlpi_name));
2169 return res;
2170}
2171
2172TSAN_INTERCEPTOR(int, dl_iterate_phdr, dl_iterate_phdr_cb_t cb, void *data) {
2173 SCOPED_TSAN_INTERCEPTOR(dl_iterate_phdr, cb, data);
2174 dl_iterate_phdr_data cbdata;
2175 cbdata.thr = thr;
2176 cbdata.pc = pc;
2177 cbdata.cb = cb;
2178 cbdata.data = data;
2179 int res = REAL(dl_iterate_phdr)(dl_iterate_phdr_cb, &cbdata);
2180 return res;
2181}
2182#endif
2183
2184static int OnExit(ThreadState *thr) {
2185 int status = Finalize(thr);
2186 FlushStreams();
2187 return status;
2188}
2189
2190struct TsanInterceptorContext {
2191 ThreadState *thr;
2192 const uptr caller_pc;
2193 const uptr pc;
2194};
2195
2196#if !SANITIZER_MAC
2197static void HandleRecvmsg(ThreadState *thr, uptr pc,
2198 __sanitizer_msghdr *msg) {
2199 int fds[64];
2200 int cnt = ExtractRecvmsgFDs(msg, fds, ARRAY_SIZE(fds));
2201 for (int i = 0; i < cnt; i++)
2202 FdEventCreate(thr, pc, fds[i]);
2203}
2204#endif
2205
2206#include "sanitizer_common/sanitizer_platform_interceptors.h"
2207// Causes interceptor recursion (getaddrinfo() and fopen())
2208#undef SANITIZER_INTERCEPT_GETADDRINFO
2209// We define our own.
2210#if SANITIZER_INTERCEPT_TLS_GET_ADDR
2211#define NEED_TLS_GET_ADDR
2212#endif
2213#undef SANITIZER_INTERCEPT_TLS_GET_ADDR
2214#undef SANITIZER_INTERCEPT_PTHREAD_SIGMASK
2215
2216#define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name)
2217#define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \
2218 INTERCEPT_FUNCTION_VER(name, ver)
2219
2220#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
2221 MemoryAccessRange(((TsanInterceptorContext *)ctx)->thr, \
2222 ((TsanInterceptorContext *)ctx)->pc, (uptr)ptr, size, \
2223 true)
2224
2225#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
2226 MemoryAccessRange(((TsanInterceptorContext *) ctx)->thr, \
2227 ((TsanInterceptorContext *) ctx)->pc, (uptr) ptr, size, \
2228 false)
2229
2230#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
2231 SCOPED_TSAN_INTERCEPTOR(func, __VA_ARGS__); \
2232 TsanInterceptorContext _ctx = {thr, caller_pc, pc}; \
2233 ctx = (void *)&_ctx; \
2234 (void) ctx;
2235
2236#define COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, func, ...) \
2237 SCOPED_INTERCEPTOR_RAW(func, __VA_ARGS__); \
2238 TsanInterceptorContext _ctx = {thr, caller_pc, pc}; \
2239 ctx = (void *)&_ctx; \
2240 (void) ctx;
2241
2242#define COMMON_INTERCEPTOR_FILE_OPEN(ctx, file, path) \
2243 if (path) \
2244 Acquire(thr, pc, File2addr(path)); \
2245 if (file) { \
2246 int fd = fileno_unlocked(file); \
2247 if (fd >= 0) FdFileCreate(thr, pc, fd); \
2248 }
2249
2250#define COMMON_INTERCEPTOR_FILE_CLOSE(ctx, file) \
2251 if (file) { \
2252 int fd = fileno_unlocked(file); \
2253 if (fd >= 0) FdClose(thr, pc, fd); \
2254 }
2255
2256#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \
2257 libignore()->OnLibraryLoaded(filename)
2258
2259#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() \
2260 libignore()->OnLibraryUnloaded()
2261
2262#define COMMON_INTERCEPTOR_ACQUIRE(ctx, u) \
2263 Acquire(((TsanInterceptorContext *) ctx)->thr, pc, u)
2264
2265#define COMMON_INTERCEPTOR_RELEASE(ctx, u) \
2266 Release(((TsanInterceptorContext *) ctx)->thr, pc, u)
2267
2268#define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
2269 Acquire(((TsanInterceptorContext *) ctx)->thr, pc, Dir2addr(path))
2270
2271#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
2272 FdAcquire(((TsanInterceptorContext *) ctx)->thr, pc, fd)
2273
2274#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
2275 FdRelease(((TsanInterceptorContext *) ctx)->thr, pc, fd)
2276
2277#define COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd) \
2278 FdAccess(((TsanInterceptorContext *) ctx)->thr, pc, fd)
2279
2280#define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
2281 FdSocketAccept(((TsanInterceptorContext *) ctx)->thr, pc, fd, newfd)
2282
2283#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \
2284 ThreadSetName(((TsanInterceptorContext *) ctx)->thr, name)
2285
2286#define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
2287 __tsan::ctx->thread_registry->SetThreadNameByUserId(thread, name)
2288
2289#define COMMON_INTERCEPTOR_BLOCK_REAL(name) BLOCK_REAL(name)
2290
2291#define COMMON_INTERCEPTOR_ON_EXIT(ctx) \
2292 OnExit(((TsanInterceptorContext *) ctx)->thr)
2293
2294#define COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m) \
2295 MutexPreLock(((TsanInterceptorContext *)ctx)->thr, \
2296 ((TsanInterceptorContext *)ctx)->pc, (uptr)m)
2297
2298#define COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m) \
2299 MutexPostLock(((TsanInterceptorContext *)ctx)->thr, \
2300 ((TsanInterceptorContext *)ctx)->pc, (uptr)m)
2301
2302#define COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m) \
2303 MutexUnlock(((TsanInterceptorContext *)ctx)->thr, \
2304 ((TsanInterceptorContext *)ctx)->pc, (uptr)m)
2305
2306#define COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m) \
2307 MutexRepair(((TsanInterceptorContext *)ctx)->thr, \
2308 ((TsanInterceptorContext *)ctx)->pc, (uptr)m)
2309
2310#define COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m) \
2311 MutexInvalidAccess(((TsanInterceptorContext *)ctx)->thr, \
2312 ((TsanInterceptorContext *)ctx)->pc, (uptr)m)
2313
2314#define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, sz, prot, flags, fd, \
2315 off) \
2316 do { \
2317 return mmap_interceptor(thr, pc, REAL(mmap), addr, sz, prot, flags, fd, \
2318 off); \
2319 } while (false)
2320
2321#if !SANITIZER_MAC
2322#define COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg) \
2323 HandleRecvmsg(((TsanInterceptorContext *)ctx)->thr, \
2324 ((TsanInterceptorContext *)ctx)->pc, msg)
2325#endif
2326
2327#define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \
2328 if (TsanThread *t = GetCurrentThread()) { \
2329 *begin = t->tls_begin(); \
2330 *end = t->tls_end(); \
2331 } else { \
2332 *begin = *end = 0; \
2333 }
2334
2335#define COMMON_INTERCEPTOR_USER_CALLBACK_START() \
2336 SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START()
2337
2338#define COMMON_INTERCEPTOR_USER_CALLBACK_END() \
2339 SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END()
2340
2341#include "sanitizer_common/sanitizer_common_interceptors.inc"
2342
2343static int sigaction_impl(int sig, const __sanitizer_sigaction *act,
2344 __sanitizer_sigaction *old);
2345static __sanitizer_sighandler_ptr signal_impl(int sig,
2346 __sanitizer_sighandler_ptr h);
2347
2348#define SIGNAL_INTERCEPTOR_SIGACTION_IMPL(signo, act, oldact) \
2349 { return sigaction_impl(signo, act, oldact); }
2350
2351#define SIGNAL_INTERCEPTOR_SIGNAL_IMPL(func, signo, handler) \
2352 { return (uptr)signal_impl(signo, (__sanitizer_sighandler_ptr)handler); }
2353
2354#include "sanitizer_common/sanitizer_signal_interceptors.inc"
2355
2356int sigaction_impl(int sig, const __sanitizer_sigaction *act,
2357 __sanitizer_sigaction *old) {
2358 // Note: if we call REAL(sigaction) directly for any reason without proxying
2359 // the signal handler through rtl_sigaction, very bad things will happen.
2360 // The handler will run synchronously and corrupt tsan per-thread state.
2361 SCOPED_INTERCEPTOR_RAW(sigaction, sig, act, old);
2362 __sanitizer_sigaction *sigactions = interceptor_ctx()->sigactions;
2363 __sanitizer_sigaction old_stored;
2364 if (old) internal_memcpy(&old_stored, &sigactions[sig], sizeof(old_stored));
2365 __sanitizer_sigaction newact;
2366 if (act) {
2367 // Copy act into sigactions[sig].
2368 // Can't use struct copy, because compiler can emit call to memcpy.
2369 // Can't use internal_memcpy, because it copies byte-by-byte,
2370 // and signal handler reads the handler concurrently. It it can read
2371 // some bytes from old value and some bytes from new value.
2372 // Use volatile to prevent insertion of memcpy.
2373 sigactions[sig].handler =
2374 *(volatile __sanitizer_sighandler_ptr const *)&act->handler;
2375 sigactions[sig].sa_flags = *(volatile int const *)&act->sa_flags;
2376 internal_memcpy(&sigactions[sig].sa_mask, &act->sa_mask,
2377 sizeof(sigactions[sig].sa_mask));
2378#if !SANITIZER_FREEBSD && !SANITIZER_MAC && !SANITIZER_NETBSD
2379 sigactions[sig].sa_restorer = act->sa_restorer;
2380#endif
2381 internal_memcpy(&newact, act, sizeof(newact));
2382 internal_sigfillset(&newact.sa_mask);
2383 if ((uptr)act->handler != sig_ign && (uptr)act->handler != sig_dfl) {
2384 if (newact.sa_flags & SA_SIGINFO)
2385 newact.sigaction = rtl_sigaction;
2386 else
2387 newact.handler = rtl_sighandler;
2388 }
2389 ReleaseStore(thr, pc, (uptr)&sigactions[sig]);
2390 act = &newact;
2391 }
2392 int res = REAL(sigaction)(sig, act, old);
2393 if (res == 0 && old) {
2394 uptr cb = (uptr)old->sigaction;
2395 if (cb == (uptr)rtl_sigaction || cb == (uptr)rtl_sighandler) {
2396 internal_memcpy(old, &old_stored, sizeof(*old));
2397 }
2398 }
2399 return res;
2400}
2401
2402static __sanitizer_sighandler_ptr signal_impl(int sig,
2403 __sanitizer_sighandler_ptr h) {
2404 __sanitizer_sigaction act;
2405 act.handler = h;
2406 internal_memset(&act.sa_mask, -1, sizeof(act.sa_mask));
2407 act.sa_flags = 0;
2408 __sanitizer_sigaction old;
2409 int res = sigaction_symname(sig, &act, &old);
2410 if (res) return (__sanitizer_sighandler_ptr)sig_err;
2411 return old.handler;
2412}
2413
2414#define TSAN_SYSCALL() \
2415 ThreadState *thr = cur_thread(); \
2416 if (thr->ignore_interceptors) \
2417 return; \
2418 ScopedSyscall scoped_syscall(thr) \
2419/**/
2420
2421struct ScopedSyscall {
2422 ThreadState *thr;
2423
2424 explicit ScopedSyscall(ThreadState *thr)
2425 : thr(thr) {
2426 Initialize(thr);
2427 }
2428
2429 ~ScopedSyscall() {
2430 ProcessPendingSignals(thr);
2431 }
2432};
2433
2434#if !SANITIZER_FREEBSD && !SANITIZER_MAC
2435static void syscall_access_range(uptr pc, uptr p, uptr s, bool write) {
2436 TSAN_SYSCALL();
2437 MemoryAccessRange(thr, pc, p, s, write);
2438}
2439
2440static void syscall_acquire(uptr pc, uptr addr) {
2441 TSAN_SYSCALL();
2442 Acquire(thr, pc, addr);
2443 DPrintf("syscall_acquire(%p)\n", addr);
2444}
2445
2446static void syscall_release(uptr pc, uptr addr) {
2447 TSAN_SYSCALL();
2448 DPrintf("syscall_release(%p)\n", addr);
2449 Release(thr, pc, addr);
2450}
2451
2452static void syscall_fd_close(uptr pc, int fd) {
2453 TSAN_SYSCALL();
2454 FdClose(thr, pc, fd);
2455}
2456
2457static USED void syscall_fd_acquire(uptr pc, int fd) {
2458 TSAN_SYSCALL();
2459 FdAcquire(thr, pc, fd);
2460 DPrintf("syscall_fd_acquire(%p)\n", fd);
2461}
2462
2463static USED void syscall_fd_release(uptr pc, int fd) {
2464 TSAN_SYSCALL();
2465 DPrintf("syscall_fd_release(%p)\n", fd);
2466 FdRelease(thr, pc, fd);
2467}
2468
2469static void syscall_pre_fork(uptr pc) {
2470 TSAN_SYSCALL();
2471 ForkBefore(thr, pc);
2472}
2473
2474static void syscall_post_fork(uptr pc, int pid) {
2475 TSAN_SYSCALL();
2476 if (pid == 0) {
2477 // child
2478 ForkChildAfter(thr, pc);
2479 FdOnFork(thr, pc);
2480 } else if (pid > 0) {
2481 // parent
2482 ForkParentAfter(thr, pc);
2483 } else {
2484 // error
2485 ForkParentAfter(thr, pc);
2486 }
2487}
2488#endif
2489
2490#define COMMON_SYSCALL_PRE_READ_RANGE(p, s) \
2491 syscall_access_range(GET_CALLER_PC(), (uptr)(p), (uptr)(s), false)
2492
2493#define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) \
2494 syscall_access_range(GET_CALLER_PC(), (uptr)(p), (uptr)(s), true)
2495
2496#define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
2497 do { \
2498 (void)(p); \
2499 (void)(s); \
2500 } while (false)
2501
2502#define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
2503 do { \
2504 (void)(p); \
2505 (void)(s); \
2506 } while (false)
2507
2508#define COMMON_SYSCALL_ACQUIRE(addr) \
2509 syscall_acquire(GET_CALLER_PC(), (uptr)(addr))
2510
2511#define COMMON_SYSCALL_RELEASE(addr) \
2512 syscall_release(GET_CALLER_PC(), (uptr)(addr))
2513
2514#define COMMON_SYSCALL_FD_CLOSE(fd) syscall_fd_close(GET_CALLER_PC(), fd)
2515
2516#define COMMON_SYSCALL_FD_ACQUIRE(fd) syscall_fd_acquire(GET_CALLER_PC(), fd)
2517
2518#define COMMON_SYSCALL_FD_RELEASE(fd) syscall_fd_release(GET_CALLER_PC(), fd)
2519
2520#define COMMON_SYSCALL_PRE_FORK() \
2521 syscall_pre_fork(GET_CALLER_PC())
2522
2523#define COMMON_SYSCALL_POST_FORK(res) \
2524 syscall_post_fork(GET_CALLER_PC(), res)
2525
2526#include "sanitizer_common/sanitizer_common_syscalls.inc"
2527#include "sanitizer_common/sanitizer_syscalls_netbsd.inc"
2528
2529#ifdef NEED_TLS_GET_ADDR
2530// Define own interceptor instead of sanitizer_common's for three reasons:
2531// 1. It must not process pending signals.
2532// Signal handlers may contain MOVDQA instruction (see below).
2533// 2. It must be as simple as possible to not contain MOVDQA.
2534// 3. Sanitizer_common version uses COMMON_INTERCEPTOR_INITIALIZE_RANGE which
2535// is empty for tsan (meant only for msan).
2536// Note: __tls_get_addr can be called with mis-aligned stack due to:
2537// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58066
2538// So the interceptor must work with mis-aligned stack, in particular, does not
2539// execute MOVDQA with stack addresses.
2540TSAN_INTERCEPTOR(void *, __tls_get_addr, void *arg) {
2541 void *res = REAL(__tls_get_addr)(arg);
2542 ThreadState *thr = cur_thread();
2543 if (!thr)
2544 return res;
2545 DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, res, thr->tls_addr,
2546 thr->tls_addr + thr->tls_size);
2547 if (!dtv)
2548 return res;
2549 // New DTLS block has been allocated.
2550 MemoryResetRange(thr, 0, dtv->beg, dtv->size);
2551 return res;
2552}
2553#endif
2554
2555#if SANITIZER_NETBSD
2556TSAN_INTERCEPTOR(void, _lwp_exit) {
2557 SCOPED_TSAN_INTERCEPTOR(_lwp_exit);
2558 DestroyThreadState();
2559 REAL(_lwp_exit)();
2560}
2561#define TSAN_MAYBE_INTERCEPT__LWP_EXIT TSAN_INTERCEPT(_lwp_exit)
2562#else
2563#define TSAN_MAYBE_INTERCEPT__LWP_EXIT
2564#endif
2565
2566#if SANITIZER_FREEBSD
2567TSAN_INTERCEPTOR(void, thr_exit, tid_t *state) {
2568 SCOPED_TSAN_INTERCEPTOR(thr_exit, state);
2569 DestroyThreadState();
2570 REAL(thr_exit(state));
2571}
2572#define TSAN_MAYBE_INTERCEPT_THR_EXIT TSAN_INTERCEPT(thr_exit)
2573#else
2574#define TSAN_MAYBE_INTERCEPT_THR_EXIT
2575#endif
2576
2577TSAN_INTERCEPTOR_NETBSD_ALIAS(int, cond_init, void *c, void *a)
2578TSAN_INTERCEPTOR_NETBSD_ALIAS(int, cond_signal, void *c)
2579TSAN_INTERCEPTOR_NETBSD_ALIAS(int, cond_broadcast, void *c)
2580TSAN_INTERCEPTOR_NETBSD_ALIAS(int, cond_wait, void *c, void *m)
2581TSAN_INTERCEPTOR_NETBSD_ALIAS(int, cond_destroy, void *c)
2582TSAN_INTERCEPTOR_NETBSD_ALIAS(int, mutex_init, void *m, void *a)
2583TSAN_INTERCEPTOR_NETBSD_ALIAS(int, mutex_destroy, void *m)
2584TSAN_INTERCEPTOR_NETBSD_ALIAS(int, mutex_trylock, void *m)
2585TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_init, void *m, void *a)
2586TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_destroy, void *m)
2587TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_rdlock, void *m)
2588TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_tryrdlock, void *m)
2589TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_wrlock, void *m)
2590TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_trywrlock, void *m)
2591TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_unlock, void *m)
2592TSAN_INTERCEPTOR_NETBSD_ALIAS_THR(int, once, void *o, void (*f)())
2593TSAN_INTERCEPTOR_NETBSD_ALIAS_THR2(int, sigsetmask, sigmask, int a, void *b,
2594 void *c)
2595
2596namespace __tsan {
2597
2598static void finalize(void *arg) {
2599 ThreadState *thr = cur_thread();
2600 int status = Finalize(thr);
2601 // Make sure the output is not lost.
2602 FlushStreams();
2603 if (status)
2604 Die();
2605}
2606
2607#if !SANITIZER_MAC && !SANITIZER_ANDROID
2608static void unreachable() {
2609 Report("FATAL: ThreadSanitizer: unreachable called\n");
2610 Die();
2611}
2612#endif
2613
2614// Define default implementation since interception of libdispatch is optional.
2615SANITIZER_WEAK_ATTRIBUTE void InitializeLibdispatchInterceptors() {}
2616
2617void InitializeInterceptors() {
2618#if !SANITIZER_MAC
2619 // We need to setup it early, because functions like dlsym() can call it.
2620 REAL(memset) = internal_memset;
2621 REAL(memcpy) = internal_memcpy;
2622#endif
2623
2624 // Instruct libc malloc to consume less memory.
2625#if SANITIZER_LINUX
2626 mallopt(1, 0); // M_MXFAST
2627 mallopt(-3, 32*1024); // M_MMAP_THRESHOLD
2628#endif
2629
2630 new(interceptor_ctx()) InterceptorContext();
2631
2632 InitializeCommonInterceptors();
2633 InitializeSignalInterceptors();
2634 InitializeLibdispatchInterceptors();
2635
2636#if !SANITIZER_MAC
2637 // We can not use TSAN_INTERCEPT to get setjmp addr,
2638 // because it does &setjmp and setjmp is not present in some versions of libc.
2639 using __interception::InterceptFunction;
2640 InterceptFunction(TSAN_STRING_SETJMP, (uptr*)&REAL(setjmp_symname), 0, 0);
2641 InterceptFunction("_setjmp", (uptr*)&REAL(_setjmp), 0, 0);
2642 InterceptFunction(TSAN_STRING_SIGSETJMP, (uptr*)&REAL(sigsetjmp_symname), 0,
2643 0);
2644#if !SANITIZER_NETBSD
2645 InterceptFunction("__sigsetjmp", (uptr*)&REAL(__sigsetjmp), 0, 0);
2646#endif
2647#endif
2648
2649 TSAN_INTERCEPT(longjmp_symname);
2650 TSAN_INTERCEPT(siglongjmp_symname);
2651#if SANITIZER_NETBSD
2652 TSAN_INTERCEPT(_longjmp);
2653#endif
2654
2655 TSAN_INTERCEPT(malloc);
2656 TSAN_INTERCEPT(__libc_memalign);
2657 TSAN_INTERCEPT(calloc);
2658 TSAN_INTERCEPT(realloc);
2659 TSAN_INTERCEPT(reallocarray);
2660 TSAN_INTERCEPT(free);
2661 TSAN_INTERCEPT(cfree);
2662 TSAN_INTERCEPT(munmap);
2663 TSAN_MAYBE_INTERCEPT_MEMALIGN;
2664 TSAN_INTERCEPT(valloc);
2665 TSAN_MAYBE_INTERCEPT_PVALLOC;
2666 TSAN_INTERCEPT(posix_memalign);
2667
2668 TSAN_INTERCEPT(strcpy);
2669 TSAN_INTERCEPT(strncpy);
2670 TSAN_INTERCEPT(strdup);
2671
2672 TSAN_INTERCEPT(pthread_create);
2673 TSAN_INTERCEPT(pthread_join);
2674 TSAN_INTERCEPT(pthread_detach);
2675 TSAN_INTERCEPT(pthread_exit);
2676 #if SANITIZER_LINUX
2677 TSAN_INTERCEPT(pthread_tryjoin_np);
2678 TSAN_INTERCEPT(pthread_timedjoin_np);
2679 #endif
2680
2681 TSAN_INTERCEPT_VER(pthread_cond_init, PTHREAD_ABI_BASE);
2682 TSAN_INTERCEPT_VER(pthread_cond_signal, PTHREAD_ABI_BASE);
2683 TSAN_INTERCEPT_VER(pthread_cond_broadcast, PTHREAD_ABI_BASE);
2684 TSAN_INTERCEPT_VER(pthread_cond_wait, PTHREAD_ABI_BASE);
2685 TSAN_INTERCEPT_VER(pthread_cond_timedwait, PTHREAD_ABI_BASE);
2686 TSAN_INTERCEPT_VER(pthread_cond_destroy, PTHREAD_ABI_BASE);
2687
2688 TSAN_INTERCEPT(pthread_mutex_init);
2689 TSAN_INTERCEPT(pthread_mutex_destroy);
2690 TSAN_INTERCEPT(pthread_mutex_trylock);
2691 TSAN_INTERCEPT(pthread_mutex_timedlock);
2692
2693 TSAN_INTERCEPT(pthread_spin_init);
2694 TSAN_INTERCEPT(pthread_spin_destroy);
2695 TSAN_INTERCEPT(pthread_spin_lock);
2696 TSAN_INTERCEPT(pthread_spin_trylock);
2697 TSAN_INTERCEPT(pthread_spin_unlock);
2698
2699 TSAN_INTERCEPT(pthread_rwlock_init);
2700 TSAN_INTERCEPT(pthread_rwlock_destroy);
2701 TSAN_INTERCEPT(pthread_rwlock_rdlock);
2702 TSAN_INTERCEPT(pthread_rwlock_tryrdlock);
2703 TSAN_INTERCEPT(pthread_rwlock_timedrdlock);
2704 TSAN_INTERCEPT(pthread_rwlock_wrlock);
2705 TSAN_INTERCEPT(pthread_rwlock_trywrlock);
2706 TSAN_INTERCEPT(pthread_rwlock_timedwrlock);
2707 TSAN_INTERCEPT(pthread_rwlock_unlock);
2708
2709 TSAN_INTERCEPT(pthread_barrier_init);
2710 TSAN_INTERCEPT(pthread_barrier_destroy);
2711 TSAN_INTERCEPT(pthread_barrier_wait);
2712
2713 TSAN_INTERCEPT(pthread_once);
2714
2715 TSAN_INTERCEPT(fstat);
2716 TSAN_MAYBE_INTERCEPT___FXSTAT;
2717 TSAN_MAYBE_INTERCEPT_FSTAT64;
2718 TSAN_MAYBE_INTERCEPT___FXSTAT64;
2719 TSAN_INTERCEPT(open);
2720 TSAN_MAYBE_INTERCEPT_OPEN64;
2721 TSAN_INTERCEPT(creat);
2722 TSAN_MAYBE_INTERCEPT_CREAT64;
2723 TSAN_INTERCEPT(dup);
2724 TSAN_INTERCEPT(dup2);
2725 TSAN_INTERCEPT(dup3);
2726 TSAN_MAYBE_INTERCEPT_EVENTFD;
2727 TSAN_MAYBE_INTERCEPT_SIGNALFD;
2728 TSAN_MAYBE_INTERCEPT_INOTIFY_INIT;
2729 TSAN_MAYBE_INTERCEPT_INOTIFY_INIT1;
2730 TSAN_INTERCEPT(socket);
2731 TSAN_INTERCEPT(socketpair);
2732 TSAN_INTERCEPT(connect);
2733 TSAN_INTERCEPT(bind);
2734 TSAN_INTERCEPT(listen);
2735 TSAN_MAYBE_INTERCEPT_EPOLL;
2736 TSAN_INTERCEPT(close);
2737 TSAN_MAYBE_INTERCEPT___CLOSE;
2738 TSAN_MAYBE_INTERCEPT___RES_ICLOSE;
2739 TSAN_INTERCEPT(pipe);
2740 TSAN_INTERCEPT(pipe2);
2741
2742 TSAN_INTERCEPT(unlink);
2743 TSAN_INTERCEPT(tmpfile);
2744 TSAN_MAYBE_INTERCEPT_TMPFILE64;
2745 TSAN_INTERCEPT(abort);
2746 TSAN_INTERCEPT(rmdir);
2747 TSAN_INTERCEPT(closedir);
2748
2749 TSAN_INTERCEPT(sigsuspend);
2750 TSAN_INTERCEPT(sigblock);
2751 TSAN_INTERCEPT(sigsetmask);
2752 TSAN_INTERCEPT(pthread_sigmask);
2753 TSAN_INTERCEPT(raise);
2754 TSAN_INTERCEPT(kill);
2755 TSAN_INTERCEPT(pthread_kill);
2756 TSAN_INTERCEPT(sleep);
2757 TSAN_INTERCEPT(usleep);
2758 TSAN_INTERCEPT(nanosleep);
2759 TSAN_INTERCEPT(pause);
2760 TSAN_INTERCEPT(gettimeofday);
2761 TSAN_INTERCEPT(getaddrinfo);
2762
2763 TSAN_INTERCEPT(fork);
2764 TSAN_INTERCEPT(vfork);
2765#if !SANITIZER_ANDROID
2766 TSAN_INTERCEPT(dl_iterate_phdr);
2767#endif
2768 TSAN_MAYBE_INTERCEPT_ON_EXIT;
2769 TSAN_INTERCEPT(__cxa_atexit);
2770 TSAN_INTERCEPT(_exit);
2771
2772#ifdef NEED_TLS_GET_ADDR
2773 TSAN_INTERCEPT(__tls_get_addr);
2774#endif
2775
2776 TSAN_MAYBE_INTERCEPT__LWP_EXIT;
2777 TSAN_MAYBE_INTERCEPT_THR_EXIT;
2778
2779#if !SANITIZER_MAC && !SANITIZER_ANDROID
2780 // Need to setup it, because interceptors check that the function is resolved.
2781 // But atexit is emitted directly into the module, so can't be resolved.
2782 REAL(atexit) = (int(*)(void(*)()))unreachable;
2783#endif
2784
2785 if (REAL(__cxa_atexit)(&finalize, 0, 0)) {
2786 Printf("ThreadSanitizer: failed to setup atexit callback\n");
2787 Die();
2788 }
2789
2790#if !SANITIZER_MAC && !SANITIZER_NETBSD && !SANITIZER_FREEBSD
2791 if (pthread_key_create(&interceptor_ctx()->finalize_key, &thread_finalize)) {
2792 Printf("ThreadSanitizer: failed to create thread key\n");
2793 Die();
2794 }
2795#endif
2796
2797 TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(cond_init);
2798 TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(cond_signal);
2799 TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(cond_broadcast);
2800 TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(cond_wait);
2801 TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(cond_destroy);
2802 TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(mutex_init);
2803 TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(mutex_destroy);
2804 TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(mutex_trylock);
2805 TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_init);
2806 TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_destroy);
2807 TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_rdlock);
2808 TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_tryrdlock);
2809 TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_wrlock);
2810 TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_trywrlock);
2811 TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_unlock);
2812 TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS_THR(once);
2813 TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS_THR(sigsetmask);
2814
2815 FdInit();
2816}
2817
2818} // namespace __tsan
2819
2820// Invisible barrier for tests.
2821// There were several unsuccessful iterations for this functionality:
2822// 1. Initially it was implemented in user code using
2823// REAL(pthread_barrier_wait). But pthread_barrier_wait is not supported on
2824// MacOS. Futexes are linux-specific for this matter.
2825// 2. Then we switched to atomics+usleep(10). But usleep produced parasitic
2826// "as-if synchronized via sleep" messages in reports which failed some
2827// output tests.
2828// 3. Then we switched to atomics+sched_yield. But this produced tons of tsan-
2829// visible events, which lead to "failed to restore stack trace" failures.
2830// Note that no_sanitize_thread attribute does not turn off atomic interception
2831// so attaching it to the function defined in user code does not help.
2832// That's why we now have what we have.
2833extern "C" SANITIZER_INTERFACE_ATTRIBUTE
2834void __tsan_testonly_barrier_init(u64 *barrier, u32 count) {
2835 if (count >= (1 << 8)) {
2836 Printf("barrier_init: count is too large (%d)\n", count);
2837 Die();
2838 }
2839 // 8 lsb is thread count, the remaining are count of entered threads.
2840 *barrier = count;
2841}
2842
2843extern "C" SANITIZER_INTERFACE_ATTRIBUTE
2844void __tsan_testonly_barrier_wait(u64 *barrier) {
2845 unsigned old = __atomic_fetch_add(barrier, 1 << 8, __ATOMIC_RELAXED);
2846 unsigned old_epoch = (old >> 8) / (old & 0xff);
2847 for (;;) {
2848 unsigned cur = __atomic_load_n(barrier, __ATOMIC_RELAXED);
2849 unsigned cur_epoch = (cur >> 8) / (cur & 0xff);
2850 if (cur_epoch != old_epoch)
2851 return;
2852 internal_sched_yield();
2853 }
2854}
lib/tsan/tsan_interface.cpp created+160
...@@ -0,0 +1,160 @@
1//===-- tsan_interface.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#include "tsan_interface.h"
14#include "tsan_interface_ann.h"
15#include "tsan_rtl.h"
16#include "sanitizer_common/sanitizer_internal_defs.h"
17
18#define CALLERPC ((uptr)__builtin_return_address(0))
19
20using namespace __tsan;
21
22typedef u16 uint16_t;
23typedef u32 uint32_t;
24typedef u64 uint64_t;
25
26void __tsan_init() {
27 cur_thread_init();
28 Initialize(cur_thread());
29}
30
31void __tsan_flush_memory() {
32 FlushShadowMemory();
33}
34
35void __tsan_read16(void *addr) {
36 MemoryRead(cur_thread(), CALLERPC, (uptr)addr, kSizeLog8);
37 MemoryRead(cur_thread(), CALLERPC, (uptr)addr + 8, kSizeLog8);
38}
39
40void __tsan_write16(void *addr) {
41 MemoryWrite(cur_thread(), CALLERPC, (uptr)addr, kSizeLog8);
42 MemoryWrite(cur_thread(), CALLERPC, (uptr)addr + 8, kSizeLog8);
43}
44
45void __tsan_read16_pc(void *addr, void *pc) {
46 MemoryRead(cur_thread(), (uptr)pc, (uptr)addr, kSizeLog8);
47 MemoryRead(cur_thread(), (uptr)pc, (uptr)addr + 8, kSizeLog8);
48}
49
50void __tsan_write16_pc(void *addr, void *pc) {
51 MemoryWrite(cur_thread(), (uptr)pc, (uptr)addr, kSizeLog8);
52 MemoryWrite(cur_thread(), (uptr)pc, (uptr)addr + 8, kSizeLog8);
53}
54
55// __tsan_unaligned_read/write calls are emitted by compiler.
56
57void __tsan_unaligned_read2(const void *addr) {
58 UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 2, false, false);
59}
60
61void __tsan_unaligned_read4(const void *addr) {
62 UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 4, false, false);
63}
64
65void __tsan_unaligned_read8(const void *addr) {
66 UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 8, false, false);
67}
68
69void __tsan_unaligned_read16(const void *addr) {
70 UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 16, false, false);
71}
72
73void __tsan_unaligned_write2(void *addr) {
74 UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 2, true, false);
75}
76
77void __tsan_unaligned_write4(void *addr) {
78 UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 4, true, false);
79}
80
81void __tsan_unaligned_write8(void *addr) {
82 UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 8, true, false);
83}
84
85void __tsan_unaligned_write16(void *addr) {
86 UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 16, true, false);
87}
88
89// __sanitizer_unaligned_load/store are for user instrumentation.
90
91extern "C" {
92SANITIZER_INTERFACE_ATTRIBUTE
93u16 __sanitizer_unaligned_load16(const uu16 *addr) {
94 __tsan_unaligned_read2(addr);
95 return *addr;
96}
97
98SANITIZER_INTERFACE_ATTRIBUTE
99u32 __sanitizer_unaligned_load32(const uu32 *addr) {
100 __tsan_unaligned_read4(addr);
101 return *addr;
102}
103
104SANITIZER_INTERFACE_ATTRIBUTE
105u64 __sanitizer_unaligned_load64(const uu64 *addr) {
106 __tsan_unaligned_read8(addr);
107 return *addr;
108}
109
110SANITIZER_INTERFACE_ATTRIBUTE
111void __sanitizer_unaligned_store16(uu16 *addr, u16 v) {
112 __tsan_unaligned_write2(addr);
113 *addr = v;
114}
115
116SANITIZER_INTERFACE_ATTRIBUTE
117void __sanitizer_unaligned_store32(uu32 *addr, u32 v) {
118 __tsan_unaligned_write4(addr);
119 *addr = v;
120}
121
122SANITIZER_INTERFACE_ATTRIBUTE
123void __sanitizer_unaligned_store64(uu64 *addr, u64 v) {
124 __tsan_unaligned_write8(addr);
125 *addr = v;
126}
127
128SANITIZER_INTERFACE_ATTRIBUTE
129void *__tsan_get_current_fiber() {
130 return cur_thread();
131}
132
133SANITIZER_INTERFACE_ATTRIBUTE
134void *__tsan_create_fiber(unsigned flags) {
135 return FiberCreate(cur_thread(), CALLERPC, flags);
136}
137
138SANITIZER_INTERFACE_ATTRIBUTE
139void __tsan_destroy_fiber(void *fiber) {
140 FiberDestroy(cur_thread(), CALLERPC, static_cast<ThreadState *>(fiber));
141}
142
143SANITIZER_INTERFACE_ATTRIBUTE
144void __tsan_switch_to_fiber(void *fiber, unsigned flags) {
145 FiberSwitch(cur_thread(), CALLERPC, static_cast<ThreadState *>(fiber), flags);
146}
147
148SANITIZER_INTERFACE_ATTRIBUTE
149void __tsan_set_fiber_name(void *fiber, const char *name) {
150 ThreadSetName(static_cast<ThreadState *>(fiber), name);
151}
152} // extern "C"
153
154void __tsan_acquire(void *addr) {
155 Acquire(cur_thread(), CALLERPC, (uptr)addr);
156}
157
158void __tsan_release(void *addr) {
159 Release(cur_thread(), CALLERPC, (uptr)addr);
160}
lib/tsan/tsan_interface.h created+422
...@@ -0,0 +1,422 @@
1//===-- tsan_interface.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// The functions declared in this header will be inserted by the instrumentation
12// module.
13// This header can be included by the instrumented program or by TSan tests.
14//===----------------------------------------------------------------------===//
15#ifndef TSAN_INTERFACE_H
16#define TSAN_INTERFACE_H
17
18#include <sanitizer_common/sanitizer_internal_defs.h>
19using __sanitizer::uptr;
20using __sanitizer::tid_t;
21
22// This header should NOT include any other headers.
23// All functions in this header are extern "C" and start with __tsan_.
24
25#ifdef __cplusplus
26extern "C" {
27#endif
28
29#if !SANITIZER_GO
30
31// This function should be called at the very beginning of the process,
32// before any instrumented code is executed and before any call to malloc.
33SANITIZER_INTERFACE_ATTRIBUTE void __tsan_init();
34
35SANITIZER_INTERFACE_ATTRIBUTE void __tsan_flush_memory();
36
37SANITIZER_INTERFACE_ATTRIBUTE void __tsan_read1(void *addr);
38SANITIZER_INTERFACE_ATTRIBUTE void __tsan_read2(void *addr);
39SANITIZER_INTERFACE_ATTRIBUTE void __tsan_read4(void *addr);
40SANITIZER_INTERFACE_ATTRIBUTE void __tsan_read8(void *addr);
41SANITIZER_INTERFACE_ATTRIBUTE void __tsan_read16(void *addr);
42
43SANITIZER_INTERFACE_ATTRIBUTE void __tsan_write1(void *addr);
44SANITIZER_INTERFACE_ATTRIBUTE void __tsan_write2(void *addr);
45SANITIZER_INTERFACE_ATTRIBUTE void __tsan_write4(void *addr);
46SANITIZER_INTERFACE_ATTRIBUTE void __tsan_write8(void *addr);
47SANITIZER_INTERFACE_ATTRIBUTE void __tsan_write16(void *addr);
48
49SANITIZER_INTERFACE_ATTRIBUTE void __tsan_unaligned_read2(const void *addr);
50SANITIZER_INTERFACE_ATTRIBUTE void __tsan_unaligned_read4(const void *addr);
51SANITIZER_INTERFACE_ATTRIBUTE void __tsan_unaligned_read8(const void *addr);
52SANITIZER_INTERFACE_ATTRIBUTE void __tsan_unaligned_read16(const void *addr);
53
54SANITIZER_INTERFACE_ATTRIBUTE void __tsan_unaligned_write2(void *addr);
55SANITIZER_INTERFACE_ATTRIBUTE void __tsan_unaligned_write4(void *addr);
56SANITIZER_INTERFACE_ATTRIBUTE void __tsan_unaligned_write8(void *addr);
57SANITIZER_INTERFACE_ATTRIBUTE void __tsan_unaligned_write16(void *addr);
58
59SANITIZER_INTERFACE_ATTRIBUTE void __tsan_read1_pc(void *addr, void *pc);
60SANITIZER_INTERFACE_ATTRIBUTE void __tsan_read2_pc(void *addr, void *pc);
61SANITIZER_INTERFACE_ATTRIBUTE void __tsan_read4_pc(void *addr, void *pc);
62SANITIZER_INTERFACE_ATTRIBUTE void __tsan_read8_pc(void *addr, void *pc);
63SANITIZER_INTERFACE_ATTRIBUTE void __tsan_read16_pc(void *addr, void *pc);
64
65SANITIZER_INTERFACE_ATTRIBUTE void __tsan_write1_pc(void *addr, void *pc);
66SANITIZER_INTERFACE_ATTRIBUTE void __tsan_write2_pc(void *addr, void *pc);
67SANITIZER_INTERFACE_ATTRIBUTE void __tsan_write4_pc(void *addr, void *pc);
68SANITIZER_INTERFACE_ATTRIBUTE void __tsan_write8_pc(void *addr, void *pc);
69SANITIZER_INTERFACE_ATTRIBUTE void __tsan_write16_pc(void *addr, void *pc);
70
71SANITIZER_INTERFACE_ATTRIBUTE void __tsan_vptr_read(void **vptr_p);
72SANITIZER_INTERFACE_ATTRIBUTE
73void __tsan_vptr_update(void **vptr_p, void *new_val);
74
75SANITIZER_INTERFACE_ATTRIBUTE void __tsan_func_entry(void *call_pc);
76SANITIZER_INTERFACE_ATTRIBUTE void __tsan_func_exit();
77
78SANITIZER_INTERFACE_ATTRIBUTE void __tsan_ignore_thread_begin();
79SANITIZER_INTERFACE_ATTRIBUTE void __tsan_ignore_thread_end();
80
81SANITIZER_INTERFACE_ATTRIBUTE
82void *__tsan_external_register_tag(const char *object_type);
83SANITIZER_INTERFACE_ATTRIBUTE
84void __tsan_external_register_header(void *tag, const char *header);
85SANITIZER_INTERFACE_ATTRIBUTE
86void __tsan_external_assign_tag(void *addr, void *tag);
87SANITIZER_INTERFACE_ATTRIBUTE
88void __tsan_external_read(void *addr, void *caller_pc, void *tag);
89SANITIZER_INTERFACE_ATTRIBUTE
90void __tsan_external_write(void *addr, void *caller_pc, void *tag);
91
92SANITIZER_INTERFACE_ATTRIBUTE
93void __tsan_read_range(void *addr, unsigned long size);
94SANITIZER_INTERFACE_ATTRIBUTE
95void __tsan_write_range(void *addr, unsigned long size);
96
97SANITIZER_INTERFACE_ATTRIBUTE
98void __tsan_read_range_pc(void *addr, unsigned long size, void *pc); // NOLINT
99SANITIZER_INTERFACE_ATTRIBUTE
100void __tsan_write_range_pc(void *addr, unsigned long size, void *pc); // NOLINT
101
102// User may provide function that would be called right when TSan detects
103// an error. The argument 'report' is an opaque pointer that can be used to
104// gather additional information using other TSan report API functions.
105SANITIZER_INTERFACE_ATTRIBUTE
106void __tsan_on_report(void *report);
107
108// If TSan is currently reporting a detected issue on the current thread,
109// returns an opaque pointer to the current report. Otherwise returns NULL.
110SANITIZER_INTERFACE_ATTRIBUTE
111void *__tsan_get_current_report();
112
113// Returns a report's description (issue type), number of duplicate issues
114// found, counts of array data (stack traces, memory operations, locations,
115// mutexes, threads, unique thread IDs) and a stack trace of a sleep() call (if
116// one was involved in the issue).
117SANITIZER_INTERFACE_ATTRIBUTE
118int __tsan_get_report_data(void *report, const char **description, int *count,
119 int *stack_count, int *mop_count, int *loc_count,
120 int *mutex_count, int *thread_count,
121 int *unique_tid_count, void **sleep_trace,
122 uptr trace_size);
123
124/// Retrieves the "tag" from a report (for external-race report types). External
125/// races can be associated with a tag which give them more meaning. For example
126/// tag value '1' means "Swift access race". Tag value '0' indicated a plain
127/// external race.
128///
129/// \param report opaque pointer to the current report (obtained as argument in
130/// __tsan_on_report, or from __tsan_get_current_report)
131/// \param [out] tag points to storage that will be filled with the tag value
132///
133/// \returns non-zero value on success, zero on failure
134SANITIZER_INTERFACE_ATTRIBUTE
135int __tsan_get_report_tag(void *report, uptr *tag);
136
137// Returns information about stack traces included in the report.
138SANITIZER_INTERFACE_ATTRIBUTE
139int __tsan_get_report_stack(void *report, uptr idx, void **trace,
140 uptr trace_size);
141
142// Returns information about memory operations included in the report.
143SANITIZER_INTERFACE_ATTRIBUTE
144int __tsan_get_report_mop(void *report, uptr idx, int *tid, void **addr,
145 int *size, int *write, int *atomic, void **trace,
146 uptr trace_size);
147
148// Returns information about locations included in the report.
149SANITIZER_INTERFACE_ATTRIBUTE
150int __tsan_get_report_loc(void *report, uptr idx, const char **type,
151 void **addr, uptr *start, uptr *size, int *tid,
152 int *fd, int *suppressable, void **trace,
153 uptr trace_size);
154
155SANITIZER_INTERFACE_ATTRIBUTE
156int __tsan_get_report_loc_object_type(void *report, uptr idx,
157 const char **object_type);
158
159// Returns information about mutexes included in the report.
160SANITIZER_INTERFACE_ATTRIBUTE
161int __tsan_get_report_mutex(void *report, uptr idx, uptr *mutex_id, void **addr,
162 int *destroyed, void **trace, uptr trace_size);
163
164// Returns information about threads included in the report.
165SANITIZER_INTERFACE_ATTRIBUTE
166int __tsan_get_report_thread(void *report, uptr idx, int *tid, tid_t *os_id,
167 int *running, const char **name, int *parent_tid,
168 void **trace, uptr trace_size);
169
170// Returns information about unique thread IDs included in the report.
171SANITIZER_INTERFACE_ATTRIBUTE
172int __tsan_get_report_unique_tid(void *report, uptr idx, int *tid);
173
174// Returns the type of the pointer (heap, stack, global, ...) and if possible
175// also the starting address (e.g. of a heap allocation) and size.
176SANITIZER_INTERFACE_ATTRIBUTE
177const char *__tsan_locate_address(uptr addr, char *name, uptr name_size,
178 uptr *region_address, uptr *region_size);
179
180// Returns the allocation stack for a heap pointer.
181SANITIZER_INTERFACE_ATTRIBUTE
182int __tsan_get_alloc_stack(uptr addr, uptr *trace, uptr size, int *thread_id,
183 tid_t *os_id);
184
185#endif // SANITIZER_GO
186
187#ifdef __cplusplus
188} // extern "C"
189#endif
190
191namespace __tsan {
192
193// These should match declarations from public tsan_interface_atomic.h header.
194typedef unsigned char a8;
195typedef unsigned short a16;
196typedef unsigned int a32;
197typedef unsigned long long a64;
198#if !SANITIZER_GO && (defined(__SIZEOF_INT128__) \
199 || (__clang_major__ * 100 + __clang_minor__ >= 302)) && !defined(__mips64)
200__extension__ typedef __int128 a128;
201# define __TSAN_HAS_INT128 1
202#else
203# define __TSAN_HAS_INT128 0
204#endif
205
206// Part of ABI, do not change.
207// https://github.com/llvm/llvm-project/blob/master/libcxx/include/atomic
208typedef enum {
209 mo_relaxed,
210 mo_consume,
211 mo_acquire,
212 mo_release,
213 mo_acq_rel,
214 mo_seq_cst
215} morder;
216
217struct ThreadState;
218
219extern "C" {
220SANITIZER_INTERFACE_ATTRIBUTE
221a8 __tsan_atomic8_load(const volatile a8 *a, morder mo);
222SANITIZER_INTERFACE_ATTRIBUTE
223a16 __tsan_atomic16_load(const volatile a16 *a, morder mo);
224SANITIZER_INTERFACE_ATTRIBUTE
225a32 __tsan_atomic32_load(const volatile a32 *a, morder mo);
226SANITIZER_INTERFACE_ATTRIBUTE
227a64 __tsan_atomic64_load(const volatile a64 *a, morder mo);
228#if __TSAN_HAS_INT128
229SANITIZER_INTERFACE_ATTRIBUTE
230a128 __tsan_atomic128_load(const volatile a128 *a, morder mo);
231#endif
232
233SANITIZER_INTERFACE_ATTRIBUTE
234void __tsan_atomic8_store(volatile a8 *a, a8 v, morder mo);
235SANITIZER_INTERFACE_ATTRIBUTE
236void __tsan_atomic16_store(volatile a16 *a, a16 v, morder mo);
237SANITIZER_INTERFACE_ATTRIBUTE
238void __tsan_atomic32_store(volatile a32 *a, a32 v, morder mo);
239SANITIZER_INTERFACE_ATTRIBUTE
240void __tsan_atomic64_store(volatile a64 *a, a64 v, morder mo);
241#if __TSAN_HAS_INT128
242SANITIZER_INTERFACE_ATTRIBUTE
243void __tsan_atomic128_store(volatile a128 *a, a128 v, morder mo);
244#endif
245
246SANITIZER_INTERFACE_ATTRIBUTE
247a8 __tsan_atomic8_exchange(volatile a8 *a, a8 v, morder mo);
248SANITIZER_INTERFACE_ATTRIBUTE
249a16 __tsan_atomic16_exchange(volatile a16 *a, a16 v, morder mo);
250SANITIZER_INTERFACE_ATTRIBUTE
251a32 __tsan_atomic32_exchange(volatile a32 *a, a32 v, morder mo);
252SANITIZER_INTERFACE_ATTRIBUTE
253a64 __tsan_atomic64_exchange(volatile a64 *a, a64 v, morder mo);
254#if __TSAN_HAS_INT128
255SANITIZER_INTERFACE_ATTRIBUTE
256a128 __tsan_atomic128_exchange(volatile a128 *a, a128 v, morder mo);
257#endif
258
259SANITIZER_INTERFACE_ATTRIBUTE
260a8 __tsan_atomic8_fetch_add(volatile a8 *a, a8 v, morder mo);
261SANITIZER_INTERFACE_ATTRIBUTE
262a16 __tsan_atomic16_fetch_add(volatile a16 *a, a16 v, morder mo);
263SANITIZER_INTERFACE_ATTRIBUTE
264a32 __tsan_atomic32_fetch_add(volatile a32 *a, a32 v, morder mo);
265SANITIZER_INTERFACE_ATTRIBUTE
266a64 __tsan_atomic64_fetch_add(volatile a64 *a, a64 v, morder mo);
267#if __TSAN_HAS_INT128
268SANITIZER_INTERFACE_ATTRIBUTE
269a128 __tsan_atomic128_fetch_add(volatile a128 *a, a128 v, morder mo);
270#endif
271
272SANITIZER_INTERFACE_ATTRIBUTE
273a8 __tsan_atomic8_fetch_sub(volatile a8 *a, a8 v, morder mo);
274SANITIZER_INTERFACE_ATTRIBUTE
275a16 __tsan_atomic16_fetch_sub(volatile a16 *a, a16 v, morder mo);
276SANITIZER_INTERFACE_ATTRIBUTE
277a32 __tsan_atomic32_fetch_sub(volatile a32 *a, a32 v, morder mo);
278SANITIZER_INTERFACE_ATTRIBUTE
279a64 __tsan_atomic64_fetch_sub(volatile a64 *a, a64 v, morder mo);
280#if __TSAN_HAS_INT128
281SANITIZER_INTERFACE_ATTRIBUTE
282a128 __tsan_atomic128_fetch_sub(volatile a128 *a, a128 v, morder mo);
283#endif
284
285SANITIZER_INTERFACE_ATTRIBUTE
286a8 __tsan_atomic8_fetch_and(volatile a8 *a, a8 v, morder mo);
287SANITIZER_INTERFACE_ATTRIBUTE
288a16 __tsan_atomic16_fetch_and(volatile a16 *a, a16 v, morder mo);
289SANITIZER_INTERFACE_ATTRIBUTE
290a32 __tsan_atomic32_fetch_and(volatile a32 *a, a32 v, morder mo);
291SANITIZER_INTERFACE_ATTRIBUTE
292a64 __tsan_atomic64_fetch_and(volatile a64 *a, a64 v, morder mo);
293#if __TSAN_HAS_INT128
294SANITIZER_INTERFACE_ATTRIBUTE
295a128 __tsan_atomic128_fetch_and(volatile a128 *a, a128 v, morder mo);
296#endif
297
298SANITIZER_INTERFACE_ATTRIBUTE
299a8 __tsan_atomic8_fetch_or(volatile a8 *a, a8 v, morder mo);
300SANITIZER_INTERFACE_ATTRIBUTE
301a16 __tsan_atomic16_fetch_or(volatile a16 *a, a16 v, morder mo);
302SANITIZER_INTERFACE_ATTRIBUTE
303a32 __tsan_atomic32_fetch_or(volatile a32 *a, a32 v, morder mo);
304SANITIZER_INTERFACE_ATTRIBUTE
305a64 __tsan_atomic64_fetch_or(volatile a64 *a, a64 v, morder mo);
306#if __TSAN_HAS_INT128
307SANITIZER_INTERFACE_ATTRIBUTE
308a128 __tsan_atomic128_fetch_or(volatile a128 *a, a128 v, morder mo);
309#endif
310
311SANITIZER_INTERFACE_ATTRIBUTE
312a8 __tsan_atomic8_fetch_xor(volatile a8 *a, a8 v, morder mo);
313SANITIZER_INTERFACE_ATTRIBUTE
314a16 __tsan_atomic16_fetch_xor(volatile a16 *a, a16 v, morder mo);
315SANITIZER_INTERFACE_ATTRIBUTE
316a32 __tsan_atomic32_fetch_xor(volatile a32 *a, a32 v, morder mo);
317SANITIZER_INTERFACE_ATTRIBUTE
318a64 __tsan_atomic64_fetch_xor(volatile a64 *a, a64 v, morder mo);
319#if __TSAN_HAS_INT128
320SANITIZER_INTERFACE_ATTRIBUTE
321a128 __tsan_atomic128_fetch_xor(volatile a128 *a, a128 v, morder mo);
322#endif
323
324SANITIZER_INTERFACE_ATTRIBUTE
325a8 __tsan_atomic8_fetch_nand(volatile a8 *a, a8 v, morder mo);
326SANITIZER_INTERFACE_ATTRIBUTE
327a16 __tsan_atomic16_fetch_nand(volatile a16 *a, a16 v, morder mo);
328SANITIZER_INTERFACE_ATTRIBUTE
329a32 __tsan_atomic32_fetch_nand(volatile a32 *a, a32 v, morder mo);
330SANITIZER_INTERFACE_ATTRIBUTE
331a64 __tsan_atomic64_fetch_nand(volatile a64 *a, a64 v, morder mo);
332#if __TSAN_HAS_INT128
333SANITIZER_INTERFACE_ATTRIBUTE
334a128 __tsan_atomic128_fetch_nand(volatile a128 *a, a128 v, morder mo);
335#endif
336
337SANITIZER_INTERFACE_ATTRIBUTE
338int __tsan_atomic8_compare_exchange_strong(volatile a8 *a, a8 *c, a8 v,
339 morder mo, morder fmo);
340SANITIZER_INTERFACE_ATTRIBUTE
341int __tsan_atomic16_compare_exchange_strong(volatile a16 *a, a16 *c, a16 v,
342 morder mo, morder fmo);
343SANITIZER_INTERFACE_ATTRIBUTE
344int __tsan_atomic32_compare_exchange_strong(volatile a32 *a, a32 *c, a32 v,
345 morder mo, morder fmo);
346SANITIZER_INTERFACE_ATTRIBUTE
347int __tsan_atomic64_compare_exchange_strong(volatile a64 *a, a64 *c, a64 v,
348 morder mo, morder fmo);
349#if __TSAN_HAS_INT128
350SANITIZER_INTERFACE_ATTRIBUTE
351int __tsan_atomic128_compare_exchange_strong(volatile a128 *a, a128 *c, a128 v,
352 morder mo, morder fmo);
353#endif
354
355SANITIZER_INTERFACE_ATTRIBUTE
356int __tsan_atomic8_compare_exchange_weak(volatile a8 *a, a8 *c, a8 v, morder mo,
357 morder fmo);
358SANITIZER_INTERFACE_ATTRIBUTE
359int __tsan_atomic16_compare_exchange_weak(volatile a16 *a, a16 *c, a16 v,
360 morder mo, morder fmo);
361SANITIZER_INTERFACE_ATTRIBUTE
362int __tsan_atomic32_compare_exchange_weak(volatile a32 *a, a32 *c, a32 v,
363 morder mo, morder fmo);
364SANITIZER_INTERFACE_ATTRIBUTE
365int __tsan_atomic64_compare_exchange_weak(volatile a64 *a, a64 *c, a64 v,
366 morder mo, morder fmo);
367#if __TSAN_HAS_INT128
368SANITIZER_INTERFACE_ATTRIBUTE
369int __tsan_atomic128_compare_exchange_weak(volatile a128 *a, a128 *c, a128 v,
370 morder mo, morder fmo);
371#endif
372
373SANITIZER_INTERFACE_ATTRIBUTE
374a8 __tsan_atomic8_compare_exchange_val(volatile a8 *a, a8 c, a8 v, morder mo,
375 morder fmo);
376SANITIZER_INTERFACE_ATTRIBUTE
377a16 __tsan_atomic16_compare_exchange_val(volatile a16 *a, a16 c, a16 v,
378 morder mo, morder fmo);
379SANITIZER_INTERFACE_ATTRIBUTE
380a32 __tsan_atomic32_compare_exchange_val(volatile a32 *a, a32 c, a32 v,
381 morder mo, morder fmo);
382SANITIZER_INTERFACE_ATTRIBUTE
383a64 __tsan_atomic64_compare_exchange_val(volatile a64 *a, a64 c, a64 v,
384 morder mo, morder fmo);
385#if __TSAN_HAS_INT128
386SANITIZER_INTERFACE_ATTRIBUTE
387a128 __tsan_atomic128_compare_exchange_val(volatile a128 *a, a128 c, a128 v,
388 morder mo, morder fmo);
389#endif
390
391SANITIZER_INTERFACE_ATTRIBUTE
392void __tsan_atomic_thread_fence(morder mo);
393SANITIZER_INTERFACE_ATTRIBUTE
394void __tsan_atomic_signal_fence(morder mo);
395
396SANITIZER_INTERFACE_ATTRIBUTE
397void __tsan_go_atomic32_load(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
398SANITIZER_INTERFACE_ATTRIBUTE
399void __tsan_go_atomic64_load(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
400SANITIZER_INTERFACE_ATTRIBUTE
401void __tsan_go_atomic32_store(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
402SANITIZER_INTERFACE_ATTRIBUTE
403void __tsan_go_atomic64_store(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
404SANITIZER_INTERFACE_ATTRIBUTE
405void __tsan_go_atomic32_fetch_add(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
406SANITIZER_INTERFACE_ATTRIBUTE
407void __tsan_go_atomic64_fetch_add(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
408SANITIZER_INTERFACE_ATTRIBUTE
409void __tsan_go_atomic32_exchange(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
410SANITIZER_INTERFACE_ATTRIBUTE
411void __tsan_go_atomic64_exchange(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
412SANITIZER_INTERFACE_ATTRIBUTE
413void __tsan_go_atomic32_compare_exchange(ThreadState *thr, uptr cpc, uptr pc,
414 u8 *a);
415SANITIZER_INTERFACE_ATTRIBUTE
416void __tsan_go_atomic64_compare_exchange(ThreadState *thr, uptr cpc, uptr pc,
417 u8 *a);
418} // extern "C"
419
420} // namespace __tsan
421
422#endif // TSAN_INTERFACE_H
lib/tsan/tsan_interface_ann.cpp created+552
...@@ -0,0 +1,552 @@
1//===-- tsan_interface_ann.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 "sanitizer_common/sanitizer_libc.h"
13#include "sanitizer_common/sanitizer_internal_defs.h"
14#include "sanitizer_common/sanitizer_placement_new.h"
15#include "sanitizer_common/sanitizer_stacktrace.h"
16#include "sanitizer_common/sanitizer_vector.h"
17#include "tsan_interface_ann.h"
18#include "tsan_mutex.h"
19#include "tsan_report.h"
20#include "tsan_rtl.h"
21#include "tsan_mman.h"
22#include "tsan_flags.h"
23#include "tsan_platform.h"
24
25#define CALLERPC ((uptr)__builtin_return_address(0))
26
27using namespace __tsan;
28
29namespace __tsan {
30
31class ScopedAnnotation {
32 public:
33 ScopedAnnotation(ThreadState *thr, const char *aname, uptr pc)
34 : thr_(thr) {
35 FuncEntry(thr_, pc);
36 DPrintf("#%d: annotation %s()\n", thr_->tid, aname);
37 }
38
39 ~ScopedAnnotation() {
40 FuncExit(thr_);
41 CheckNoLocks(thr_);
42 }
43 private:
44 ThreadState *const thr_;
45};
46
47#define SCOPED_ANNOTATION_RET(typ, ret) \
48 if (!flags()->enable_annotations) \
49 return ret; \
50 ThreadState *thr = cur_thread(); \
51 const uptr caller_pc = (uptr)__builtin_return_address(0); \
52 StatInc(thr, StatAnnotation); \
53 StatInc(thr, Stat##typ); \
54 ScopedAnnotation sa(thr, __func__, caller_pc); \
55 const uptr pc = StackTrace::GetCurrentPc(); \
56 (void)pc; \
57/**/
58
59#define SCOPED_ANNOTATION(typ) SCOPED_ANNOTATION_RET(typ, )
60
61static const int kMaxDescLen = 128;
62
63struct ExpectRace {
64 ExpectRace *next;
65 ExpectRace *prev;
66 atomic_uintptr_t hitcount;
67 atomic_uintptr_t addcount;
68 uptr addr;
69 uptr size;
70 char *file;
71 int line;
72 char desc[kMaxDescLen];
73};
74
75struct DynamicAnnContext {
76 Mutex mtx;
77 ExpectRace expect;
78 ExpectRace benign;
79
80 DynamicAnnContext()
81 : mtx(MutexTypeAnnotations, StatMtxAnnotations) {
82 }
83};
84
85static DynamicAnnContext *dyn_ann_ctx;
86static char dyn_ann_ctx_placeholder[sizeof(DynamicAnnContext)] ALIGNED(64);
87
88static void AddExpectRace(ExpectRace *list,
89 char *f, int l, uptr addr, uptr size, char *desc) {
90 ExpectRace *race = list->next;
91 for (; race != list; race = race->next) {
92 if (race->addr == addr && race->size == size) {
93 atomic_store_relaxed(&race->addcount,
94 atomic_load_relaxed(&race->addcount) + 1);
95 return;
96 }
97 }
98 race = (ExpectRace*)internal_alloc(MBlockExpectRace, sizeof(ExpectRace));
99 race->addr = addr;
100 race->size = size;
101 race->file = f;
102 race->line = l;
103 race->desc[0] = 0;
104 atomic_store_relaxed(&race->hitcount, 0);
105 atomic_store_relaxed(&race->addcount, 1);
106 if (desc) {
107 int i = 0;
108 for (; i < kMaxDescLen - 1 && desc[i]; i++)
109 race->desc[i] = desc[i];
110 race->desc[i] = 0;
111 }
112 race->prev = list;
113 race->next = list->next;
114 race->next->prev = race;
115 list->next = race;
116}
117
118static ExpectRace *FindRace(ExpectRace *list, uptr addr, uptr size) {
119 for (ExpectRace *race = list->next; race != list; race = race->next) {
120 uptr maxbegin = max(race->addr, addr);
121 uptr minend = min(race->addr + race->size, addr + size);
122 if (maxbegin < minend)
123 return race;
124 }
125 return 0;
126}
127
128static bool CheckContains(ExpectRace *list, uptr addr, uptr size) {
129 ExpectRace *race = FindRace(list, addr, size);
130 if (race == 0)
131 return false;
132 DPrintf("Hit expected/benign race: %s addr=%zx:%d %s:%d\n",
133 race->desc, race->addr, (int)race->size, race->file, race->line);
134 atomic_fetch_add(&race->hitcount, 1, memory_order_relaxed);
135 return true;
136}
137
138static void InitList(ExpectRace *list) {
139 list->next = list;
140 list->prev = list;
141}
142
143void InitializeDynamicAnnotations() {
144 dyn_ann_ctx = new(dyn_ann_ctx_placeholder) DynamicAnnContext;
145 InitList(&dyn_ann_ctx->expect);
146 InitList(&dyn_ann_ctx->benign);
147}
148
149bool IsExpectedReport(uptr addr, uptr size) {
150 ReadLock lock(&dyn_ann_ctx->mtx);
151 if (CheckContains(&dyn_ann_ctx->expect, addr, size))
152 return true;
153 if (CheckContains(&dyn_ann_ctx->benign, addr, size))
154 return true;
155 return false;
156}
157
158static void CollectMatchedBenignRaces(Vector<ExpectRace> *matched,
159 int *unique_count, int *hit_count, atomic_uintptr_t ExpectRace::*counter) {
160 ExpectRace *list = &dyn_ann_ctx->benign;
161 for (ExpectRace *race = list->next; race != list; race = race->next) {
162 (*unique_count)++;
163 const uptr cnt = atomic_load_relaxed(&(race->*counter));
164 if (cnt == 0)
165 continue;
166 *hit_count += cnt;
167 uptr i = 0;
168 for (; i < matched->Size(); i++) {
169 ExpectRace *race0 = &(*matched)[i];
170 if (race->line == race0->line
171 && internal_strcmp(race->file, race0->file) == 0
172 && internal_strcmp(race->desc, race0->desc) == 0) {
173 atomic_fetch_add(&(race0->*counter), cnt, memory_order_relaxed);
174 break;
175 }
176 }
177 if (i == matched->Size())
178 matched->PushBack(*race);
179 }
180}
181
182void PrintMatchedBenignRaces() {
183 Lock lock(&dyn_ann_ctx->mtx);
184 int unique_count = 0;
185 int hit_count = 0;
186 int add_count = 0;
187 Vector<ExpectRace> hit_matched;
188 CollectMatchedBenignRaces(&hit_matched, &unique_count, &hit_count,
189 &ExpectRace::hitcount);
190 Vector<ExpectRace> add_matched;
191 CollectMatchedBenignRaces(&add_matched, &unique_count, &add_count,
192 &ExpectRace::addcount);
193 if (hit_matched.Size()) {
194 Printf("ThreadSanitizer: Matched %d \"benign\" races (pid=%d):\n",
195 hit_count, (int)internal_getpid());
196 for (uptr i = 0; i < hit_matched.Size(); i++) {
197 Printf("%d %s:%d %s\n",
198 atomic_load_relaxed(&hit_matched[i].hitcount),
199 hit_matched[i].file, hit_matched[i].line, hit_matched[i].desc);
200 }
201 }
202 if (hit_matched.Size()) {
203 Printf("ThreadSanitizer: Annotated %d \"benign\" races, %d unique"
204 " (pid=%d):\n",
205 add_count, unique_count, (int)internal_getpid());
206 for (uptr i = 0; i < add_matched.Size(); i++) {
207 Printf("%d %s:%d %s\n",
208 atomic_load_relaxed(&add_matched[i].addcount),
209 add_matched[i].file, add_matched[i].line, add_matched[i].desc);
210 }
211 }
212}
213
214static void ReportMissedExpectedRace(ExpectRace *race) {
215 Printf("==================\n");
216 Printf("WARNING: ThreadSanitizer: missed expected data race\n");
217 Printf(" %s addr=%zx %s:%d\n",
218 race->desc, race->addr, race->file, race->line);
219 Printf("==================\n");
220}
221} // namespace __tsan
222
223using namespace __tsan;
224
225extern "C" {
226void INTERFACE_ATTRIBUTE AnnotateHappensBefore(char *f, int l, uptr addr) {
227 SCOPED_ANNOTATION(AnnotateHappensBefore);
228 Release(thr, pc, addr);
229}
230
231void INTERFACE_ATTRIBUTE AnnotateHappensAfter(char *f, int l, uptr addr) {
232 SCOPED_ANNOTATION(AnnotateHappensAfter);
233 Acquire(thr, pc, addr);
234}
235
236void INTERFACE_ATTRIBUTE AnnotateCondVarSignal(char *f, int l, uptr cv) {
237 SCOPED_ANNOTATION(AnnotateCondVarSignal);
238}
239
240void INTERFACE_ATTRIBUTE AnnotateCondVarSignalAll(char *f, int l, uptr cv) {
241 SCOPED_ANNOTATION(AnnotateCondVarSignalAll);
242}
243
244void INTERFACE_ATTRIBUTE AnnotateMutexIsNotPHB(char *f, int l, uptr mu) {
245 SCOPED_ANNOTATION(AnnotateMutexIsNotPHB);
246}
247
248void INTERFACE_ATTRIBUTE AnnotateCondVarWait(char *f, int l, uptr cv,
249 uptr lock) {
250 SCOPED_ANNOTATION(AnnotateCondVarWait);
251}
252
253void INTERFACE_ATTRIBUTE AnnotateRWLockCreate(char *f, int l, uptr m) {
254 SCOPED_ANNOTATION(AnnotateRWLockCreate);
255 MutexCreate(thr, pc, m, MutexFlagWriteReentrant);
256}
257
258void INTERFACE_ATTRIBUTE AnnotateRWLockCreateStatic(char *f, int l, uptr m) {
259 SCOPED_ANNOTATION(AnnotateRWLockCreateStatic);
260 MutexCreate(thr, pc, m, MutexFlagWriteReentrant | MutexFlagLinkerInit);
261}
262
263void INTERFACE_ATTRIBUTE AnnotateRWLockDestroy(char *f, int l, uptr m) {
264 SCOPED_ANNOTATION(AnnotateRWLockDestroy);
265 MutexDestroy(thr, pc, m);
266}
267
268void INTERFACE_ATTRIBUTE AnnotateRWLockAcquired(char *f, int l, uptr m,
269 uptr is_w) {
270 SCOPED_ANNOTATION(AnnotateRWLockAcquired);
271 if (is_w)
272 MutexPostLock(thr, pc, m, MutexFlagDoPreLockOnPostLock);
273 else
274 MutexPostReadLock(thr, pc, m, MutexFlagDoPreLockOnPostLock);
275}
276
277void INTERFACE_ATTRIBUTE AnnotateRWLockReleased(char *f, int l, uptr m,
278 uptr is_w) {
279 SCOPED_ANNOTATION(AnnotateRWLockReleased);
280 if (is_w)
281 MutexUnlock(thr, pc, m);
282 else
283 MutexReadUnlock(thr, pc, m);
284}
285
286void INTERFACE_ATTRIBUTE AnnotateTraceMemory(char *f, int l, uptr mem) {
287 SCOPED_ANNOTATION(AnnotateTraceMemory);
288}
289
290void INTERFACE_ATTRIBUTE AnnotateFlushState(char *f, int l) {
291 SCOPED_ANNOTATION(AnnotateFlushState);
292}
293
294void INTERFACE_ATTRIBUTE AnnotateNewMemory(char *f, int l, uptr mem,
295 uptr size) {
296 SCOPED_ANNOTATION(AnnotateNewMemory);
297}
298
299void INTERFACE_ATTRIBUTE AnnotateNoOp(char *f, int l, uptr mem) {
300 SCOPED_ANNOTATION(AnnotateNoOp);
301}
302
303void INTERFACE_ATTRIBUTE AnnotateFlushExpectedRaces(char *f, int l) {
304 SCOPED_ANNOTATION(AnnotateFlushExpectedRaces);
305 Lock lock(&dyn_ann_ctx->mtx);
306 while (dyn_ann_ctx->expect.next != &dyn_ann_ctx->expect) {
307 ExpectRace *race = dyn_ann_ctx->expect.next;
308 if (atomic_load_relaxed(&race->hitcount) == 0) {
309 ctx->nmissed_expected++;
310 ReportMissedExpectedRace(race);
311 }
312 race->prev->next = race->next;
313 race->next->prev = race->prev;
314 internal_free(race);
315 }
316}
317
318void INTERFACE_ATTRIBUTE AnnotateEnableRaceDetection(
319 char *f, int l, int enable) {
320 SCOPED_ANNOTATION(AnnotateEnableRaceDetection);
321 // FIXME: Reconsider this functionality later. It may be irrelevant.
322}
323
324void INTERFACE_ATTRIBUTE AnnotateMutexIsUsedAsCondVar(
325 char *f, int l, uptr mu) {
326 SCOPED_ANNOTATION(AnnotateMutexIsUsedAsCondVar);
327}
328
329void INTERFACE_ATTRIBUTE AnnotatePCQGet(
330 char *f, int l, uptr pcq) {
331 SCOPED_ANNOTATION(AnnotatePCQGet);
332}
333
334void INTERFACE_ATTRIBUTE AnnotatePCQPut(
335 char *f, int l, uptr pcq) {
336 SCOPED_ANNOTATION(AnnotatePCQPut);
337}
338
339void INTERFACE_ATTRIBUTE AnnotatePCQDestroy(
340 char *f, int l, uptr pcq) {
341 SCOPED_ANNOTATION(AnnotatePCQDestroy);
342}
343
344void INTERFACE_ATTRIBUTE AnnotatePCQCreate(
345 char *f, int l, uptr pcq) {
346 SCOPED_ANNOTATION(AnnotatePCQCreate);
347}
348
349void INTERFACE_ATTRIBUTE AnnotateExpectRace(
350 char *f, int l, uptr mem, char *desc) {
351 SCOPED_ANNOTATION(AnnotateExpectRace);
352 Lock lock(&dyn_ann_ctx->mtx);
353 AddExpectRace(&dyn_ann_ctx->expect,
354 f, l, mem, 1, desc);
355 DPrintf("Add expected race: %s addr=%zx %s:%d\n", desc, mem, f, l);
356}
357
358static void BenignRaceImpl(
359 char *f, int l, uptr mem, uptr size, char *desc) {
360 Lock lock(&dyn_ann_ctx->mtx);
361 AddExpectRace(&dyn_ann_ctx->benign,
362 f, l, mem, size, desc);
363 DPrintf("Add benign race: %s addr=%zx %s:%d\n", desc, mem, f, l);
364}
365
366// FIXME: Turn it off later. WTF is benign race?1?? Go talk to Hans Boehm.
367void INTERFACE_ATTRIBUTE AnnotateBenignRaceSized(
368 char *f, int l, uptr mem, uptr size, char *desc) {
369 SCOPED_ANNOTATION(AnnotateBenignRaceSized);
370 BenignRaceImpl(f, l, mem, size, desc);
371}
372
373void INTERFACE_ATTRIBUTE AnnotateBenignRace(
374 char *f, int l, uptr mem, char *desc) {
375 SCOPED_ANNOTATION(AnnotateBenignRace);
376 BenignRaceImpl(f, l, mem, 1, desc);
377}
378
379void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsBegin(char *f, int l) {
380 SCOPED_ANNOTATION(AnnotateIgnoreReadsBegin);
381 ThreadIgnoreBegin(thr, pc);
382}
383
384void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsEnd(char *f, int l) {
385 SCOPED_ANNOTATION(AnnotateIgnoreReadsEnd);
386 ThreadIgnoreEnd(thr, pc);
387}
388
389void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesBegin(char *f, int l) {
390 SCOPED_ANNOTATION(AnnotateIgnoreWritesBegin);
391 ThreadIgnoreBegin(thr, pc);
392}
393
394void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesEnd(char *f, int l) {
395 SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd);
396 ThreadIgnoreEnd(thr, pc);
397}
398
399void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncBegin(char *f, int l) {
400 SCOPED_ANNOTATION(AnnotateIgnoreSyncBegin);
401 ThreadIgnoreSyncBegin(thr, pc);
402}
403
404void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncEnd(char *f, int l) {
405 SCOPED_ANNOTATION(AnnotateIgnoreSyncEnd);
406 ThreadIgnoreSyncEnd(thr, pc);
407}
408
409void INTERFACE_ATTRIBUTE AnnotatePublishMemoryRange(
410 char *f, int l, uptr addr, uptr size) {
411 SCOPED_ANNOTATION(AnnotatePublishMemoryRange);
412}
413
414void INTERFACE_ATTRIBUTE AnnotateUnpublishMemoryRange(
415 char *f, int l, uptr addr, uptr size) {
416 SCOPED_ANNOTATION(AnnotateUnpublishMemoryRange);
417}
418
419void INTERFACE_ATTRIBUTE AnnotateThreadName(
420 char *f, int l, char *name) {
421 SCOPED_ANNOTATION(AnnotateThreadName);
422 ThreadSetName(thr, name);
423}
424
425// We deliberately omit the implementation of WTFAnnotateHappensBefore() and
426// WTFAnnotateHappensAfter(). Those are being used by Webkit to annotate
427// atomic operations, which should be handled by ThreadSanitizer correctly.
428void INTERFACE_ATTRIBUTE WTFAnnotateHappensBefore(char *f, int l, uptr addr) {
429 SCOPED_ANNOTATION(AnnotateHappensBefore);
430}
431
432void INTERFACE_ATTRIBUTE WTFAnnotateHappensAfter(char *f, int l, uptr addr) {
433 SCOPED_ANNOTATION(AnnotateHappensAfter);
434}
435
436void INTERFACE_ATTRIBUTE WTFAnnotateBenignRaceSized(
437 char *f, int l, uptr mem, uptr sz, char *desc) {
438 SCOPED_ANNOTATION(AnnotateBenignRaceSized);
439 BenignRaceImpl(f, l, mem, sz, desc);
440}
441
442int INTERFACE_ATTRIBUTE RunningOnValgrind() {
443 return flags()->running_on_valgrind;
444}
445
446double __attribute__((weak)) INTERFACE_ATTRIBUTE ValgrindSlowdown(void) {
447 return 10.0;
448}
449
450const char INTERFACE_ATTRIBUTE* ThreadSanitizerQuery(const char *query) {
451 if (internal_strcmp(query, "pure_happens_before") == 0)
452 return "1";
453 else
454 return "0";
455}
456
457void INTERFACE_ATTRIBUTE
458AnnotateMemoryIsInitialized(char *f, int l, uptr mem, uptr sz) {}
459void INTERFACE_ATTRIBUTE
460AnnotateMemoryIsUninitialized(char *f, int l, uptr mem, uptr sz) {}
461
462// Note: the parameter is called flagz, because flags is already taken
463// by the global function that returns flags.
464INTERFACE_ATTRIBUTE
465void __tsan_mutex_create(void *m, unsigned flagz) {
466 SCOPED_ANNOTATION(__tsan_mutex_create);
467 MutexCreate(thr, pc, (uptr)m, flagz & MutexCreationFlagMask);
468}
469
470INTERFACE_ATTRIBUTE
471void __tsan_mutex_destroy(void *m, unsigned flagz) {
472 SCOPED_ANNOTATION(__tsan_mutex_destroy);
473 MutexDestroy(thr, pc, (uptr)m, flagz);
474}
475
476INTERFACE_ATTRIBUTE
477void __tsan_mutex_pre_lock(void *m, unsigned flagz) {
478 SCOPED_ANNOTATION(__tsan_mutex_pre_lock);
479 if (!(flagz & MutexFlagTryLock)) {
480 if (flagz & MutexFlagReadLock)
481 MutexPreReadLock(thr, pc, (uptr)m);
482 else
483 MutexPreLock(thr, pc, (uptr)m);
484 }
485 ThreadIgnoreBegin(thr, pc, /*save_stack=*/false);
486 ThreadIgnoreSyncBegin(thr, pc, /*save_stack=*/false);
487}
488
489INTERFACE_ATTRIBUTE
490void __tsan_mutex_post_lock(void *m, unsigned flagz, int rec) {
491 SCOPED_ANNOTATION(__tsan_mutex_post_lock);
492 ThreadIgnoreSyncEnd(thr, pc);
493 ThreadIgnoreEnd(thr, pc);
494 if (!(flagz & MutexFlagTryLockFailed)) {
495 if (flagz & MutexFlagReadLock)
496 MutexPostReadLock(thr, pc, (uptr)m, flagz);
497 else
498 MutexPostLock(thr, pc, (uptr)m, flagz, rec);
499 }
500}
501
502INTERFACE_ATTRIBUTE
503int __tsan_mutex_pre_unlock(void *m, unsigned flagz) {
504 SCOPED_ANNOTATION_RET(__tsan_mutex_pre_unlock, 0);
505 int ret = 0;
506 if (flagz & MutexFlagReadLock) {
507 CHECK(!(flagz & MutexFlagRecursiveUnlock));
508 MutexReadUnlock(thr, pc, (uptr)m);
509 } else {
510 ret = MutexUnlock(thr, pc, (uptr)m, flagz);
511 }
512 ThreadIgnoreBegin(thr, pc, /*save_stack=*/false);
513 ThreadIgnoreSyncBegin(thr, pc, /*save_stack=*/false);
514 return ret;
515}
516
517INTERFACE_ATTRIBUTE
518void __tsan_mutex_post_unlock(void *m, unsigned flagz) {
519 SCOPED_ANNOTATION(__tsan_mutex_post_unlock);
520 ThreadIgnoreSyncEnd(thr, pc);
521 ThreadIgnoreEnd(thr, pc);
522}
523
524INTERFACE_ATTRIBUTE
525void __tsan_mutex_pre_signal(void *addr, unsigned flagz) {
526 SCOPED_ANNOTATION(__tsan_mutex_pre_signal);
527 ThreadIgnoreBegin(thr, pc, /*save_stack=*/false);
528 ThreadIgnoreSyncBegin(thr, pc, /*save_stack=*/false);
529}
530
531INTERFACE_ATTRIBUTE
532void __tsan_mutex_post_signal(void *addr, unsigned flagz) {
533 SCOPED_ANNOTATION(__tsan_mutex_post_signal);
534 ThreadIgnoreSyncEnd(thr, pc);
535 ThreadIgnoreEnd(thr, pc);
536}
537
538INTERFACE_ATTRIBUTE
539void __tsan_mutex_pre_divert(void *addr, unsigned flagz) {
540 SCOPED_ANNOTATION(__tsan_mutex_pre_divert);
541 // Exit from ignore region started in __tsan_mutex_pre_lock/unlock/signal.
542 ThreadIgnoreSyncEnd(thr, pc);
543 ThreadIgnoreEnd(thr, pc);
544}
545
546INTERFACE_ATTRIBUTE
547void __tsan_mutex_post_divert(void *addr, unsigned flagz) {
548 SCOPED_ANNOTATION(__tsan_mutex_post_divert);
549 ThreadIgnoreBegin(thr, pc, /*save_stack=*/false);
550 ThreadIgnoreSyncBegin(thr, pc, /*save_stack=*/false);
551}
552} // extern "C"
lib/tsan/tsan_interface_ann.h created+32
...@@ -0,0 +1,32 @@
1//===-- tsan_interface_ann.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// Interface for dynamic annotations.
12//===----------------------------------------------------------------------===//
13#ifndef TSAN_INTERFACE_ANN_H
14#define TSAN_INTERFACE_ANN_H
15
16#include <sanitizer_common/sanitizer_internal_defs.h>
17
18// This header should NOT include any other headers.
19// All functions in this header are extern "C" and start with __tsan_.
20
21#ifdef __cplusplus
22extern "C" {
23#endif
24
25SANITIZER_INTERFACE_ATTRIBUTE void __tsan_acquire(void *addr);
26SANITIZER_INTERFACE_ATTRIBUTE void __tsan_release(void *addr);
27
28#ifdef __cplusplus
29} // extern "C"
30#endif
31
32#endif // TSAN_INTERFACE_ANN_H
lib/tsan/tsan_interface_atomic.cpp created+955
...@@ -0,0 +1,955 @@
1//===-- tsan_interface_atomic.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// ThreadSanitizer atomic operations are based on C++11/C1x standards.
14// For background see C++11 standard. A slightly older, publicly
15// available draft of the standard (not entirely up-to-date, but close enough
16// for casual browsing) is available here:
17// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf
18// The following page contains more background information:
19// http://www.hpl.hp.com/personal/Hans_Boehm/c++mm/
20
21#include "sanitizer_common/sanitizer_placement_new.h"
22#include "sanitizer_common/sanitizer_stacktrace.h"
23#include "sanitizer_common/sanitizer_mutex.h"
24#include "tsan_flags.h"
25#include "tsan_interface.h"
26#include "tsan_rtl.h"
27
28using namespace __tsan;
29
30#if !SANITIZER_GO && __TSAN_HAS_INT128
31// Protects emulation of 128-bit atomic operations.
32static StaticSpinMutex mutex128;
33#endif
34
35static bool IsLoadOrder(morder mo) {
36 return mo == mo_relaxed || mo == mo_consume
37 || mo == mo_acquire || mo == mo_seq_cst;
38}
39
40static bool IsStoreOrder(morder mo) {
41 return mo == mo_relaxed || mo == mo_release || mo == mo_seq_cst;
42}
43
44static bool IsReleaseOrder(morder mo) {
45 return mo == mo_release || mo == mo_acq_rel || mo == mo_seq_cst;
46}
47
48static bool IsAcquireOrder(morder mo) {
49 return mo == mo_consume || mo == mo_acquire
50 || mo == mo_acq_rel || mo == mo_seq_cst;
51}
52
53static bool IsAcqRelOrder(morder mo) {
54 return mo == mo_acq_rel || mo == mo_seq_cst;
55}
56
57template<typename T> T func_xchg(volatile T *v, T op) {
58 T res = __sync_lock_test_and_set(v, op);
59 // __sync_lock_test_and_set does not contain full barrier.
60 __sync_synchronize();
61 return res;
62}
63
64template<typename T> T func_add(volatile T *v, T op) {
65 return __sync_fetch_and_add(v, op);
66}
67
68template<typename T> T func_sub(volatile T *v, T op) {
69 return __sync_fetch_and_sub(v, op);
70}
71
72template<typename T> T func_and(volatile T *v, T op) {
73 return __sync_fetch_and_and(v, op);
74}
75
76template<typename T> T func_or(volatile T *v, T op) {
77 return __sync_fetch_and_or(v, op);
78}
79
80template<typename T> T func_xor(volatile T *v, T op) {
81 return __sync_fetch_and_xor(v, op);
82}
83
84template<typename T> T func_nand(volatile T *v, T op) {
85 // clang does not support __sync_fetch_and_nand.
86 T cmp = *v;
87 for (;;) {
88 T newv = ~(cmp & op);
89 T cur = __sync_val_compare_and_swap(v, cmp, newv);
90 if (cmp == cur)
91 return cmp;
92 cmp = cur;
93 }
94}
95
96template<typename T> T func_cas(volatile T *v, T cmp, T xch) {
97 return __sync_val_compare_and_swap(v, cmp, xch);
98}
99
100// clang does not support 128-bit atomic ops.
101// Atomic ops are executed under tsan internal mutex,
102// here we assume that the atomic variables are not accessed
103// from non-instrumented code.
104#if !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) && !SANITIZER_GO \
105 && __TSAN_HAS_INT128
106a128 func_xchg(volatile a128 *v, a128 op) {
107 SpinMutexLock lock(&mutex128);
108 a128 cmp = *v;
109 *v = op;
110 return cmp;
111}
112
113a128 func_add(volatile a128 *v, a128 op) {
114 SpinMutexLock lock(&mutex128);
115 a128 cmp = *v;
116 *v = cmp + op;
117 return cmp;
118}
119
120a128 func_sub(volatile a128 *v, a128 op) {
121 SpinMutexLock lock(&mutex128);
122 a128 cmp = *v;
123 *v = cmp - op;
124 return cmp;
125}
126
127a128 func_and(volatile a128 *v, a128 op) {
128 SpinMutexLock lock(&mutex128);
129 a128 cmp = *v;
130 *v = cmp & op;
131 return cmp;
132}
133
134a128 func_or(volatile a128 *v, a128 op) {
135 SpinMutexLock lock(&mutex128);
136 a128 cmp = *v;
137 *v = cmp | op;
138 return cmp;
139}
140
141a128 func_xor(volatile a128 *v, a128 op) {
142 SpinMutexLock lock(&mutex128);
143 a128 cmp = *v;
144 *v = cmp ^ op;
145 return cmp;
146}
147
148a128 func_nand(volatile a128 *v, a128 op) {
149 SpinMutexLock lock(&mutex128);
150 a128 cmp = *v;
151 *v = ~(cmp & op);
152 return cmp;
153}
154
155a128 func_cas(volatile a128 *v, a128 cmp, a128 xch) {
156 SpinMutexLock lock(&mutex128);
157 a128 cur = *v;
158 if (cur == cmp)
159 *v = xch;
160 return cur;
161}
162#endif
163
164template<typename T>
165static int SizeLog() {
166 if (sizeof(T) <= 1)
167 return kSizeLog1;
168 else if (sizeof(T) <= 2)
169 return kSizeLog2;
170 else if (sizeof(T) <= 4)
171 return kSizeLog4;
172 else
173 return kSizeLog8;
174 // For 16-byte atomics we also use 8-byte memory access,
175 // this leads to false negatives only in very obscure cases.
176}
177
178#if !SANITIZER_GO
179static atomic_uint8_t *to_atomic(const volatile a8 *a) {
180 return reinterpret_cast<atomic_uint8_t *>(const_cast<a8 *>(a));
181}
182
183static atomic_uint16_t *to_atomic(const volatile a16 *a) {
184 return reinterpret_cast<atomic_uint16_t *>(const_cast<a16 *>(a));
185}
186#endif
187
188static atomic_uint32_t *to_atomic(const volatile a32 *a) {
189 return reinterpret_cast<atomic_uint32_t *>(const_cast<a32 *>(a));
190}
191
192static atomic_uint64_t *to_atomic(const volatile a64 *a) {
193 return reinterpret_cast<atomic_uint64_t *>(const_cast<a64 *>(a));
194}
195
196static memory_order to_mo(morder mo) {
197 switch (mo) {
198 case mo_relaxed: return memory_order_relaxed;
199 case mo_consume: return memory_order_consume;
200 case mo_acquire: return memory_order_acquire;
201 case mo_release: return memory_order_release;
202 case mo_acq_rel: return memory_order_acq_rel;
203 case mo_seq_cst: return memory_order_seq_cst;
204 }
205 CHECK(0);
206 return memory_order_seq_cst;
207}
208
209template<typename T>
210static T NoTsanAtomicLoad(const volatile T *a, morder mo) {
211 return atomic_load(to_atomic(a), to_mo(mo));
212}
213
214#if __TSAN_HAS_INT128 && !SANITIZER_GO
215static a128 NoTsanAtomicLoad(const volatile a128 *a, morder mo) {
216 SpinMutexLock lock(&mutex128);
217 return *a;
218}
219#endif
220
221template<typename T>
222static T AtomicLoad(ThreadState *thr, uptr pc, const volatile T *a, morder mo) {
223 CHECK(IsLoadOrder(mo));
224 // This fast-path is critical for performance.
225 // Assume the access is atomic.
226 if (!IsAcquireOrder(mo)) {
227 MemoryReadAtomic(thr, pc, (uptr)a, SizeLog<T>());
228 return NoTsanAtomicLoad(a, mo);
229 }
230 // Don't create sync object if it does not exist yet. For example, an atomic
231 // pointer is initialized to nullptr and then periodically acquire-loaded.
232 T v = NoTsanAtomicLoad(a, mo);
233 SyncVar *s = ctx->metamap.GetIfExistsAndLock((uptr)a, false);
234 if (s) {
235 AcquireImpl(thr, pc, &s->clock);
236 // Re-read under sync mutex because we need a consistent snapshot
237 // of the value and the clock we acquire.
238 v = NoTsanAtomicLoad(a, mo);
239 s->mtx.ReadUnlock();
240 }
241 MemoryReadAtomic(thr, pc, (uptr)a, SizeLog<T>());
242 return v;
243}
244
245template<typename T>
246static void NoTsanAtomicStore(volatile T *a, T v, morder mo) {
247 atomic_store(to_atomic(a), v, to_mo(mo));
248}
249
250#if __TSAN_HAS_INT128 && !SANITIZER_GO
251static void NoTsanAtomicStore(volatile a128 *a, a128 v, morder mo) {
252 SpinMutexLock lock(&mutex128);
253 *a = v;
254}
255#endif
256
257template<typename T>
258static void AtomicStore(ThreadState *thr, uptr pc, volatile T *a, T v,
259 morder mo) {
260 CHECK(IsStoreOrder(mo));
261 MemoryWriteAtomic(thr, pc, (uptr)a, SizeLog<T>());
262 // This fast-path is critical for performance.
263 // Assume the access is atomic.
264 // Strictly saying even relaxed store cuts off release sequence,
265 // so must reset the clock.
266 if (!IsReleaseOrder(mo)) {
267 NoTsanAtomicStore(a, v, mo);
268 return;
269 }
270 __sync_synchronize();
271 SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, (uptr)a, true);
272 thr->fast_state.IncrementEpoch();
273 // Can't increment epoch w/o writing to the trace as well.
274 TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
275 ReleaseStoreImpl(thr, pc, &s->clock);
276 NoTsanAtomicStore(a, v, mo);
277 s->mtx.Unlock();
278}
279
280template<typename T, T (*F)(volatile T *v, T op)>
281static T AtomicRMW(ThreadState *thr, uptr pc, volatile T *a, T v, morder mo) {
282 MemoryWriteAtomic(thr, pc, (uptr)a, SizeLog<T>());
283 SyncVar *s = 0;
284 if (mo != mo_relaxed) {
285 s = ctx->metamap.GetOrCreateAndLock(thr, pc, (uptr)a, true);
286 thr->fast_state.IncrementEpoch();
287 // Can't increment epoch w/o writing to the trace as well.
288 TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
289 if (IsAcqRelOrder(mo))
290 AcquireReleaseImpl(thr, pc, &s->clock);
291 else if (IsReleaseOrder(mo))
292 ReleaseImpl(thr, pc, &s->clock);
293 else if (IsAcquireOrder(mo))
294 AcquireImpl(thr, pc, &s->clock);
295 }
296 v = F(a, v);
297 if (s)
298 s->mtx.Unlock();
299 return v;
300}
301
302template<typename T>
303static T NoTsanAtomicExchange(volatile T *a, T v, morder mo) {
304 return func_xchg(a, v);
305}
306
307template<typename T>
308static T NoTsanAtomicFetchAdd(volatile T *a, T v, morder mo) {
309 return func_add(a, v);
310}
311
312template<typename T>
313static T NoTsanAtomicFetchSub(volatile T *a, T v, morder mo) {
314 return func_sub(a, v);
315}
316
317template<typename T>
318static T NoTsanAtomicFetchAnd(volatile T *a, T v, morder mo) {
319 return func_and(a, v);
320}
321
322template<typename T>
323static T NoTsanAtomicFetchOr(volatile T *a, T v, morder mo) {
324 return func_or(a, v);
325}
326
327template<typename T>
328static T NoTsanAtomicFetchXor(volatile T *a, T v, morder mo) {
329 return func_xor(a, v);
330}
331
332template<typename T>
333static T NoTsanAtomicFetchNand(volatile T *a, T v, morder mo) {
334 return func_nand(a, v);
335}
336
337template<typename T>
338static T AtomicExchange(ThreadState *thr, uptr pc, volatile T *a, T v,
339 morder mo) {
340 return AtomicRMW<T, func_xchg>(thr, pc, a, v, mo);
341}
342
343template<typename T>
344static T AtomicFetchAdd(ThreadState *thr, uptr pc, volatile T *a, T v,
345 morder mo) {
346 return AtomicRMW<T, func_add>(thr, pc, a, v, mo);
347}
348
349template<typename T>
350static T AtomicFetchSub(ThreadState *thr, uptr pc, volatile T *a, T v,
351 morder mo) {
352 return AtomicRMW<T, func_sub>(thr, pc, a, v, mo);
353}
354
355template<typename T>
356static T AtomicFetchAnd(ThreadState *thr, uptr pc, volatile T *a, T v,
357 morder mo) {
358 return AtomicRMW<T, func_and>(thr, pc, a, v, mo);
359}
360
361template<typename T>
362static T AtomicFetchOr(ThreadState *thr, uptr pc, volatile T *a, T v,
363 morder mo) {
364 return AtomicRMW<T, func_or>(thr, pc, a, v, mo);
365}
366
367template<typename T>
368static T AtomicFetchXor(ThreadState *thr, uptr pc, volatile T *a, T v,
369 morder mo) {
370 return AtomicRMW<T, func_xor>(thr, pc, a, v, mo);
371}
372
373template<typename T>
374static T AtomicFetchNand(ThreadState *thr, uptr pc, volatile T *a, T v,
375 morder mo) {
376 return AtomicRMW<T, func_nand>(thr, pc, a, v, mo);
377}
378
379template<typename T>
380static bool NoTsanAtomicCAS(volatile T *a, T *c, T v, morder mo, morder fmo) {
381 return atomic_compare_exchange_strong(to_atomic(a), c, v, to_mo(mo));
382}
383
384#if __TSAN_HAS_INT128
385static bool NoTsanAtomicCAS(volatile a128 *a, a128 *c, a128 v,
386 morder mo, morder fmo) {
387 a128 old = *c;
388 a128 cur = func_cas(a, old, v);
389 if (cur == old)
390 return true;
391 *c = cur;
392 return false;
393}
394#endif
395
396template<typename T>
397static T NoTsanAtomicCAS(volatile T *a, T c, T v, morder mo, morder fmo) {
398 NoTsanAtomicCAS(a, &c, v, mo, fmo);
399 return c;
400}
401
402template<typename T>
403static bool AtomicCAS(ThreadState *thr, uptr pc,
404 volatile T *a, T *c, T v, morder mo, morder fmo) {
405 (void)fmo; // Unused because llvm does not pass it yet.
406 MemoryWriteAtomic(thr, pc, (uptr)a, SizeLog<T>());
407 SyncVar *s = 0;
408 bool write_lock = mo != mo_acquire && mo != mo_consume;
409 if (mo != mo_relaxed) {
410 s = ctx->metamap.GetOrCreateAndLock(thr, pc, (uptr)a, write_lock);
411 thr->fast_state.IncrementEpoch();
412 // Can't increment epoch w/o writing to the trace as well.
413 TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
414 if (IsAcqRelOrder(mo))
415 AcquireReleaseImpl(thr, pc, &s->clock);
416 else if (IsReleaseOrder(mo))
417 ReleaseImpl(thr, pc, &s->clock);
418 else if (IsAcquireOrder(mo))
419 AcquireImpl(thr, pc, &s->clock);
420 }
421 T cc = *c;
422 T pr = func_cas(a, cc, v);
423 if (s) {
424 if (write_lock)
425 s->mtx.Unlock();
426 else
427 s->mtx.ReadUnlock();
428 }
429 if (pr == cc)
430 return true;
431 *c = pr;
432 return false;
433}
434
435template<typename T>
436static T AtomicCAS(ThreadState *thr, uptr pc,
437 volatile T *a, T c, T v, morder mo, morder fmo) {
438 AtomicCAS(thr, pc, a, &c, v, mo, fmo);
439 return c;
440}
441
442#if !SANITIZER_GO
443static void NoTsanAtomicFence(morder mo) {
444 __sync_synchronize();
445}
446
447static void AtomicFence(ThreadState *thr, uptr pc, morder mo) {
448 // FIXME(dvyukov): not implemented.
449 __sync_synchronize();
450}
451#endif
452
453// Interface functions follow.
454#if !SANITIZER_GO
455
456// C/C++
457
458static morder convert_morder(morder mo) {
459 if (flags()->force_seq_cst_atomics)
460 return (morder)mo_seq_cst;
461
462 // Filter out additional memory order flags:
463 // MEMMODEL_SYNC = 1 << 15
464 // __ATOMIC_HLE_ACQUIRE = 1 << 16
465 // __ATOMIC_HLE_RELEASE = 1 << 17
466 //
467 // HLE is an optimization, and we pretend that elision always fails.
468 // MEMMODEL_SYNC is used when lowering __sync_ atomics,
469 // since we use __sync_ atomics for actual atomic operations,
470 // we can safely ignore it as well. It also subtly affects semantics,
471 // but we don't model the difference.
472 return (morder)(mo & 0x7fff);
473}
474
475#define SCOPED_ATOMIC(func, ...) \
476 ThreadState *const thr = cur_thread(); \
477 if (UNLIKELY(thr->ignore_sync || thr->ignore_interceptors)) { \
478 ProcessPendingSignals(thr); \
479 return NoTsanAtomic##func(__VA_ARGS__); \
480 } \
481 const uptr callpc = (uptr)__builtin_return_address(0); \
482 uptr pc = StackTrace::GetCurrentPc(); \
483 mo = convert_morder(mo); \
484 AtomicStatInc(thr, sizeof(*a), mo, StatAtomic##func); \
485 ScopedAtomic sa(thr, callpc, a, mo, __func__); \
486 return Atomic##func(thr, pc, __VA_ARGS__); \
487/**/
488
489class ScopedAtomic {
490 public:
491 ScopedAtomic(ThreadState *thr, uptr pc, const volatile void *a,
492 morder mo, const char *func)
493 : thr_(thr) {
494 FuncEntry(thr_, pc);
495 DPrintf("#%d: %s(%p, %d)\n", thr_->tid, func, a, mo);
496 }
497 ~ScopedAtomic() {
498 ProcessPendingSignals(thr_);
499 FuncExit(thr_);
500 }
501 private:
502 ThreadState *thr_;
503};
504
505static void AtomicStatInc(ThreadState *thr, uptr size, morder mo, StatType t) {
506 StatInc(thr, StatAtomic);
507 StatInc(thr, t);
508 StatInc(thr, size == 1 ? StatAtomic1
509 : size == 2 ? StatAtomic2
510 : size == 4 ? StatAtomic4
511 : size == 8 ? StatAtomic8
512 : StatAtomic16);
513 StatInc(thr, mo == mo_relaxed ? StatAtomicRelaxed
514 : mo == mo_consume ? StatAtomicConsume
515 : mo == mo_acquire ? StatAtomicAcquire
516 : mo == mo_release ? StatAtomicRelease
517 : mo == mo_acq_rel ? StatAtomicAcq_Rel
518 : StatAtomicSeq_Cst);
519}
520
521extern "C" {
522SANITIZER_INTERFACE_ATTRIBUTE
523a8 __tsan_atomic8_load(const volatile a8 *a, morder mo) {
524 SCOPED_ATOMIC(Load, a, mo);
525}
526
527SANITIZER_INTERFACE_ATTRIBUTE
528a16 __tsan_atomic16_load(const volatile a16 *a, morder mo) {
529 SCOPED_ATOMIC(Load, a, mo);
530}
531
532SANITIZER_INTERFACE_ATTRIBUTE
533a32 __tsan_atomic32_load(const volatile a32 *a, morder mo) {
534 SCOPED_ATOMIC(Load, a, mo);
535}
536
537SANITIZER_INTERFACE_ATTRIBUTE
538a64 __tsan_atomic64_load(const volatile a64 *a, morder mo) {
539 SCOPED_ATOMIC(Load, a, mo);
540}
541
542#if __TSAN_HAS_INT128
543SANITIZER_INTERFACE_ATTRIBUTE
544a128 __tsan_atomic128_load(const volatile a128 *a, morder mo) {
545 SCOPED_ATOMIC(Load, a, mo);
546}
547#endif
548
549SANITIZER_INTERFACE_ATTRIBUTE
550void __tsan_atomic8_store(volatile a8 *a, a8 v, morder mo) {
551 SCOPED_ATOMIC(Store, a, v, mo);
552}
553
554SANITIZER_INTERFACE_ATTRIBUTE
555void __tsan_atomic16_store(volatile a16 *a, a16 v, morder mo) {
556 SCOPED_ATOMIC(Store, a, v, mo);
557}
558
559SANITIZER_INTERFACE_ATTRIBUTE
560void __tsan_atomic32_store(volatile a32 *a, a32 v, morder mo) {
561 SCOPED_ATOMIC(Store, a, v, mo);
562}
563
564SANITIZER_INTERFACE_ATTRIBUTE
565void __tsan_atomic64_store(volatile a64 *a, a64 v, morder mo) {
566 SCOPED_ATOMIC(Store, a, v, mo);
567}
568
569#if __TSAN_HAS_INT128
570SANITIZER_INTERFACE_ATTRIBUTE
571void __tsan_atomic128_store(volatile a128 *a, a128 v, morder mo) {
572 SCOPED_ATOMIC(Store, a, v, mo);
573}
574#endif
575
576SANITIZER_INTERFACE_ATTRIBUTE
577a8 __tsan_atomic8_exchange(volatile a8 *a, a8 v, morder mo) {
578 SCOPED_ATOMIC(Exchange, a, v, mo);
579}
580
581SANITIZER_INTERFACE_ATTRIBUTE
582a16 __tsan_atomic16_exchange(volatile a16 *a, a16 v, morder mo) {
583 SCOPED_ATOMIC(Exchange, a, v, mo);
584}
585
586SANITIZER_INTERFACE_ATTRIBUTE
587a32 __tsan_atomic32_exchange(volatile a32 *a, a32 v, morder mo) {
588 SCOPED_ATOMIC(Exchange, a, v, mo);
589}
590
591SANITIZER_INTERFACE_ATTRIBUTE
592a64 __tsan_atomic64_exchange(volatile a64 *a, a64 v, morder mo) {
593 SCOPED_ATOMIC(Exchange, a, v, mo);
594}
595
596#if __TSAN_HAS_INT128
597SANITIZER_INTERFACE_ATTRIBUTE
598a128 __tsan_atomic128_exchange(volatile a128 *a, a128 v, morder mo) {
599 SCOPED_ATOMIC(Exchange, a, v, mo);
600}
601#endif
602
603SANITIZER_INTERFACE_ATTRIBUTE
604a8 __tsan_atomic8_fetch_add(volatile a8 *a, a8 v, morder mo) {
605 SCOPED_ATOMIC(FetchAdd, a, v, mo);
606}
607
608SANITIZER_INTERFACE_ATTRIBUTE
609a16 __tsan_atomic16_fetch_add(volatile a16 *a, a16 v, morder mo) {
610 SCOPED_ATOMIC(FetchAdd, a, v, mo);
611}
612
613SANITIZER_INTERFACE_ATTRIBUTE
614a32 __tsan_atomic32_fetch_add(volatile a32 *a, a32 v, morder mo) {
615 SCOPED_ATOMIC(FetchAdd, a, v, mo);
616}
617
618SANITIZER_INTERFACE_ATTRIBUTE
619a64 __tsan_atomic64_fetch_add(volatile a64 *a, a64 v, morder mo) {
620 SCOPED_ATOMIC(FetchAdd, a, v, mo);
621}
622
623#if __TSAN_HAS_INT128
624SANITIZER_INTERFACE_ATTRIBUTE
625a128 __tsan_atomic128_fetch_add(volatile a128 *a, a128 v, morder mo) {
626 SCOPED_ATOMIC(FetchAdd, a, v, mo);
627}
628#endif
629
630SANITIZER_INTERFACE_ATTRIBUTE
631a8 __tsan_atomic8_fetch_sub(volatile a8 *a, a8 v, morder mo) {
632 SCOPED_ATOMIC(FetchSub, a, v, mo);
633}
634
635SANITIZER_INTERFACE_ATTRIBUTE
636a16 __tsan_atomic16_fetch_sub(volatile a16 *a, a16 v, morder mo) {
637 SCOPED_ATOMIC(FetchSub, a, v, mo);
638}
639
640SANITIZER_INTERFACE_ATTRIBUTE
641a32 __tsan_atomic32_fetch_sub(volatile a32 *a, a32 v, morder mo) {
642 SCOPED_ATOMIC(FetchSub, a, v, mo);
643}
644
645SANITIZER_INTERFACE_ATTRIBUTE
646a64 __tsan_atomic64_fetch_sub(volatile a64 *a, a64 v, morder mo) {
647 SCOPED_ATOMIC(FetchSub, a, v, mo);
648}
649
650#if __TSAN_HAS_INT128
651SANITIZER_INTERFACE_ATTRIBUTE
652a128 __tsan_atomic128_fetch_sub(volatile a128 *a, a128 v, morder mo) {
653 SCOPED_ATOMIC(FetchSub, a, v, mo);
654}
655#endif
656
657SANITIZER_INTERFACE_ATTRIBUTE
658a8 __tsan_atomic8_fetch_and(volatile a8 *a, a8 v, morder mo) {
659 SCOPED_ATOMIC(FetchAnd, a, v, mo);
660}
661
662SANITIZER_INTERFACE_ATTRIBUTE
663a16 __tsan_atomic16_fetch_and(volatile a16 *a, a16 v, morder mo) {
664 SCOPED_ATOMIC(FetchAnd, a, v, mo);
665}
666
667SANITIZER_INTERFACE_ATTRIBUTE
668a32 __tsan_atomic32_fetch_and(volatile a32 *a, a32 v, morder mo) {
669 SCOPED_ATOMIC(FetchAnd, a, v, mo);
670}
671
672SANITIZER_INTERFACE_ATTRIBUTE
673a64 __tsan_atomic64_fetch_and(volatile a64 *a, a64 v, morder mo) {
674 SCOPED_ATOMIC(FetchAnd, a, v, mo);
675}
676
677#if __TSAN_HAS_INT128
678SANITIZER_INTERFACE_ATTRIBUTE
679a128 __tsan_atomic128_fetch_and(volatile a128 *a, a128 v, morder mo) {
680 SCOPED_ATOMIC(FetchAnd, a, v, mo);
681}
682#endif
683
684SANITIZER_INTERFACE_ATTRIBUTE
685a8 __tsan_atomic8_fetch_or(volatile a8 *a, a8 v, morder mo) {
686 SCOPED_ATOMIC(FetchOr, a, v, mo);
687}
688
689SANITIZER_INTERFACE_ATTRIBUTE
690a16 __tsan_atomic16_fetch_or(volatile a16 *a, a16 v, morder mo) {
691 SCOPED_ATOMIC(FetchOr, a, v, mo);
692}
693
694SANITIZER_INTERFACE_ATTRIBUTE
695a32 __tsan_atomic32_fetch_or(volatile a32 *a, a32 v, morder mo) {
696 SCOPED_ATOMIC(FetchOr, a, v, mo);
697}
698
699SANITIZER_INTERFACE_ATTRIBUTE
700a64 __tsan_atomic64_fetch_or(volatile a64 *a, a64 v, morder mo) {
701 SCOPED_ATOMIC(FetchOr, a, v, mo);
702}
703
704#if __TSAN_HAS_INT128
705SANITIZER_INTERFACE_ATTRIBUTE
706a128 __tsan_atomic128_fetch_or(volatile a128 *a, a128 v, morder mo) {
707 SCOPED_ATOMIC(FetchOr, a, v, mo);
708}
709#endif
710
711SANITIZER_INTERFACE_ATTRIBUTE
712a8 __tsan_atomic8_fetch_xor(volatile a8 *a, a8 v, morder mo) {
713 SCOPED_ATOMIC(FetchXor, a, v, mo);
714}
715
716SANITIZER_INTERFACE_ATTRIBUTE
717a16 __tsan_atomic16_fetch_xor(volatile a16 *a, a16 v, morder mo) {
718 SCOPED_ATOMIC(FetchXor, a, v, mo);
719}
720
721SANITIZER_INTERFACE_ATTRIBUTE
722a32 __tsan_atomic32_fetch_xor(volatile a32 *a, a32 v, morder mo) {
723 SCOPED_ATOMIC(FetchXor, a, v, mo);
724}
725
726SANITIZER_INTERFACE_ATTRIBUTE
727a64 __tsan_atomic64_fetch_xor(volatile a64 *a, a64 v, morder mo) {
728 SCOPED_ATOMIC(FetchXor, a, v, mo);
729}
730
731#if __TSAN_HAS_INT128
732SANITIZER_INTERFACE_ATTRIBUTE
733a128 __tsan_atomic128_fetch_xor(volatile a128 *a, a128 v, morder mo) {
734 SCOPED_ATOMIC(FetchXor, a, v, mo);
735}
736#endif
737
738SANITIZER_INTERFACE_ATTRIBUTE
739a8 __tsan_atomic8_fetch_nand(volatile a8 *a, a8 v, morder mo) {
740 SCOPED_ATOMIC(FetchNand, a, v, mo);
741}
742
743SANITIZER_INTERFACE_ATTRIBUTE
744a16 __tsan_atomic16_fetch_nand(volatile a16 *a, a16 v, morder mo) {
745 SCOPED_ATOMIC(FetchNand, a, v, mo);
746}
747
748SANITIZER_INTERFACE_ATTRIBUTE
749a32 __tsan_atomic32_fetch_nand(volatile a32 *a, a32 v, morder mo) {
750 SCOPED_ATOMIC(FetchNand, a, v, mo);
751}
752
753SANITIZER_INTERFACE_ATTRIBUTE
754a64 __tsan_atomic64_fetch_nand(volatile a64 *a, a64 v, morder mo) {
755 SCOPED_ATOMIC(FetchNand, a, v, mo);
756}
757
758#if __TSAN_HAS_INT128
759SANITIZER_INTERFACE_ATTRIBUTE
760a128 __tsan_atomic128_fetch_nand(volatile a128 *a, a128 v, morder mo) {
761 SCOPED_ATOMIC(FetchNand, a, v, mo);
762}
763#endif
764
765SANITIZER_INTERFACE_ATTRIBUTE
766int __tsan_atomic8_compare_exchange_strong(volatile a8 *a, a8 *c, a8 v,
767 morder mo, morder fmo) {
768 SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
769}
770
771SANITIZER_INTERFACE_ATTRIBUTE
772int __tsan_atomic16_compare_exchange_strong(volatile a16 *a, a16 *c, a16 v,
773 morder mo, morder fmo) {
774 SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
775}
776
777SANITIZER_INTERFACE_ATTRIBUTE
778int __tsan_atomic32_compare_exchange_strong(volatile a32 *a, a32 *c, a32 v,
779 morder mo, morder fmo) {
780 SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
781}
782
783SANITIZER_INTERFACE_ATTRIBUTE
784int __tsan_atomic64_compare_exchange_strong(volatile a64 *a, a64 *c, a64 v,
785 morder mo, morder fmo) {
786 SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
787}
788
789#if __TSAN_HAS_INT128
790SANITIZER_INTERFACE_ATTRIBUTE
791int __tsan_atomic128_compare_exchange_strong(volatile a128 *a, a128 *c, a128 v,
792 morder mo, morder fmo) {
793 SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
794}
795#endif
796
797SANITIZER_INTERFACE_ATTRIBUTE
798int __tsan_atomic8_compare_exchange_weak(volatile a8 *a, a8 *c, a8 v,
799 morder mo, morder fmo) {
800 SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
801}
802
803SANITIZER_INTERFACE_ATTRIBUTE
804int __tsan_atomic16_compare_exchange_weak(volatile a16 *a, a16 *c, a16 v,
805 morder mo, morder fmo) {
806 SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
807}
808
809SANITIZER_INTERFACE_ATTRIBUTE
810int __tsan_atomic32_compare_exchange_weak(volatile a32 *a, a32 *c, a32 v,
811 morder mo, morder fmo) {
812 SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
813}
814
815SANITIZER_INTERFACE_ATTRIBUTE
816int __tsan_atomic64_compare_exchange_weak(volatile a64 *a, a64 *c, a64 v,
817 morder mo, morder fmo) {
818 SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
819}
820
821#if __TSAN_HAS_INT128
822SANITIZER_INTERFACE_ATTRIBUTE
823int __tsan_atomic128_compare_exchange_weak(volatile a128 *a, a128 *c, a128 v,
824 morder mo, morder fmo) {
825 SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
826}
827#endif
828
829SANITIZER_INTERFACE_ATTRIBUTE
830a8 __tsan_atomic8_compare_exchange_val(volatile a8 *a, a8 c, a8 v,
831 morder mo, morder fmo) {
832 SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
833}
834
835SANITIZER_INTERFACE_ATTRIBUTE
836a16 __tsan_atomic16_compare_exchange_val(volatile a16 *a, a16 c, a16 v,
837 morder mo, morder fmo) {
838 SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
839}
840
841SANITIZER_INTERFACE_ATTRIBUTE
842a32 __tsan_atomic32_compare_exchange_val(volatile a32 *a, a32 c, a32 v,
843 morder mo, morder fmo) {
844 SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
845}
846
847SANITIZER_INTERFACE_ATTRIBUTE
848a64 __tsan_atomic64_compare_exchange_val(volatile a64 *a, a64 c, a64 v,
849 morder mo, morder fmo) {
850 SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
851}
852
853#if __TSAN_HAS_INT128
854SANITIZER_INTERFACE_ATTRIBUTE
855a128 __tsan_atomic128_compare_exchange_val(volatile a128 *a, a128 c, a128 v,
856 morder mo, morder fmo) {
857 SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
858}
859#endif
860
861SANITIZER_INTERFACE_ATTRIBUTE
862void __tsan_atomic_thread_fence(morder mo) {
863 char* a = 0;
864 SCOPED_ATOMIC(Fence, mo);
865}
866
867SANITIZER_INTERFACE_ATTRIBUTE
868void __tsan_atomic_signal_fence(morder mo) {
869}
870} // extern "C"
871
872#else // #if !SANITIZER_GO
873
874// Go
875
876#define ATOMIC(func, ...) \
877 if (thr->ignore_sync) { \
878 NoTsanAtomic##func(__VA_ARGS__); \
879 } else { \
880 FuncEntry(thr, cpc); \
881 Atomic##func(thr, pc, __VA_ARGS__); \
882 FuncExit(thr); \
883 } \
884/**/
885
886#define ATOMIC_RET(func, ret, ...) \
887 if (thr->ignore_sync) { \
888 (ret) = NoTsanAtomic##func(__VA_ARGS__); \
889 } else { \
890 FuncEntry(thr, cpc); \
891 (ret) = Atomic##func(thr, pc, __VA_ARGS__); \
892 FuncExit(thr); \
893 } \
894/**/
895
896extern "C" {
897SANITIZER_INTERFACE_ATTRIBUTE
898void __tsan_go_atomic32_load(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
899 ATOMIC_RET(Load, *(a32*)(a+8), *(a32**)a, mo_acquire);
900}
901
902SANITIZER_INTERFACE_ATTRIBUTE
903void __tsan_go_atomic64_load(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
904 ATOMIC_RET(Load, *(a64*)(a+8), *(a64**)a, mo_acquire);
905}
906
907SANITIZER_INTERFACE_ATTRIBUTE
908void __tsan_go_atomic32_store(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
909 ATOMIC(Store, *(a32**)a, *(a32*)(a+8), mo_release);
910}
911
912SANITIZER_INTERFACE_ATTRIBUTE
913void __tsan_go_atomic64_store(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
914 ATOMIC(Store, *(a64**)a, *(a64*)(a+8), mo_release);
915}
916
917SANITIZER_INTERFACE_ATTRIBUTE
918void __tsan_go_atomic32_fetch_add(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
919 ATOMIC_RET(FetchAdd, *(a32*)(a+16), *(a32**)a, *(a32*)(a+8), mo_acq_rel);
920}
921
922SANITIZER_INTERFACE_ATTRIBUTE
923void __tsan_go_atomic64_fetch_add(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
924 ATOMIC_RET(FetchAdd, *(a64*)(a+16), *(a64**)a, *(a64*)(a+8), mo_acq_rel);
925}
926
927SANITIZER_INTERFACE_ATTRIBUTE
928void __tsan_go_atomic32_exchange(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
929 ATOMIC_RET(Exchange, *(a32*)(a+16), *(a32**)a, *(a32*)(a+8), mo_acq_rel);
930}
931
932SANITIZER_INTERFACE_ATTRIBUTE
933void __tsan_go_atomic64_exchange(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
934 ATOMIC_RET(Exchange, *(a64*)(a+16), *(a64**)a, *(a64*)(a+8), mo_acq_rel);
935}
936
937SANITIZER_INTERFACE_ATTRIBUTE
938void __tsan_go_atomic32_compare_exchange(
939 ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
940 a32 cur = 0;
941 a32 cmp = *(a32*)(a+8);
942 ATOMIC_RET(CAS, cur, *(a32**)a, cmp, *(a32*)(a+12), mo_acq_rel, mo_acquire);
943 *(bool*)(a+16) = (cur == cmp);
944}
945
946SANITIZER_INTERFACE_ATTRIBUTE
947void __tsan_go_atomic64_compare_exchange(
948 ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
949 a64 cur = 0;
950 a64 cmp = *(a64*)(a+8);
951 ATOMIC_RET(CAS, cur, *(a64**)a, cmp, *(a64*)(a+16), mo_acq_rel, mo_acquire);
952 *(bool*)(a+24) = (cur == cmp);
953}
954} // extern "C"
955#endif // #if !SANITIZER_GO
lib/tsan/tsan_interface_inl.h created+132
...@@ -0,0 +1,132 @@
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
16#define CALLERPC ((uptr)__builtin_return_address(0))
17
18using namespace __tsan;
19
20void __tsan_read1(void *addr) {
21 MemoryRead(cur_thread(), CALLERPC, (uptr)addr, kSizeLog1);
22}
23
24void __tsan_read2(void *addr) {
25 MemoryRead(cur_thread(), CALLERPC, (uptr)addr, kSizeLog2);
26}
27
28void __tsan_read4(void *addr) {
29 MemoryRead(cur_thread(), CALLERPC, (uptr)addr, kSizeLog4);
30}
31
32void __tsan_read8(void *addr) {
33 MemoryRead(cur_thread(), CALLERPC, (uptr)addr, kSizeLog8);
34}
35
36void __tsan_write1(void *addr) {
37 MemoryWrite(cur_thread(), CALLERPC, (uptr)addr, kSizeLog1);
38}
39
40void __tsan_write2(void *addr) {
41 MemoryWrite(cur_thread(), CALLERPC, (uptr)addr, kSizeLog2);
42}
43
44void __tsan_write4(void *addr) {
45 MemoryWrite(cur_thread(), CALLERPC, (uptr)addr, kSizeLog4);
46}
47
48void __tsan_write8(void *addr) {
49 MemoryWrite(cur_thread(), CALLERPC, (uptr)addr, kSizeLog8);
50}
51
52void __tsan_read1_pc(void *addr, void *pc) {
53 MemoryRead(cur_thread(), (uptr)pc, (uptr)addr, kSizeLog1);
54}
55
56void __tsan_read2_pc(void *addr, void *pc) {
57 MemoryRead(cur_thread(), (uptr)pc, (uptr)addr, kSizeLog2);
58}
59
60void __tsan_read4_pc(void *addr, void *pc) {
61 MemoryRead(cur_thread(), (uptr)pc, (uptr)addr, kSizeLog4);
62}
63
64void __tsan_read8_pc(void *addr, void *pc) {
65 MemoryRead(cur_thread(), (uptr)pc, (uptr)addr, kSizeLog8);
66}
67
68void __tsan_write1_pc(void *addr, void *pc) {
69 MemoryWrite(cur_thread(), (uptr)pc, (uptr)addr, kSizeLog1);
70}
71
72void __tsan_write2_pc(void *addr, void *pc) {
73 MemoryWrite(cur_thread(), (uptr)pc, (uptr)addr, kSizeLog2);
74}
75
76void __tsan_write4_pc(void *addr, void *pc) {
77 MemoryWrite(cur_thread(), (uptr)pc, (uptr)addr, kSizeLog4);
78}
79
80void __tsan_write8_pc(void *addr, void *pc) {
81 MemoryWrite(cur_thread(), (uptr)pc, (uptr)addr, kSizeLog8);
82}
83
84void __tsan_vptr_update(void **vptr_p, void *new_val) {
85 CHECK_EQ(sizeof(vptr_p), 8);
86 if (*vptr_p != new_val) {
87 ThreadState *thr = cur_thread();
88 thr->is_vptr_access = true;
89 MemoryWrite(thr, CALLERPC, (uptr)vptr_p, kSizeLog8);
90 thr->is_vptr_access = false;
91 }
92}
93
94void __tsan_vptr_read(void **vptr_p) {
95 CHECK_EQ(sizeof(vptr_p), 8);
96 ThreadState *thr = cur_thread();
97 thr->is_vptr_access = true;
98 MemoryRead(thr, CALLERPC, (uptr)vptr_p, kSizeLog8);
99 thr->is_vptr_access = false;
100}
101
102void __tsan_func_entry(void *pc) {
103 FuncEntry(cur_thread(), (uptr)pc);
104}
105
106void __tsan_func_exit() {
107 FuncExit(cur_thread());
108}
109
110void __tsan_ignore_thread_begin() {
111 ThreadIgnoreBegin(cur_thread(), CALLERPC);
112}
113
114void __tsan_ignore_thread_end() {
115 ThreadIgnoreEnd(cur_thread(), CALLERPC);
116}
117
118void __tsan_read_range(void *addr, uptr size) {
119 MemoryAccessRange(cur_thread(), CALLERPC, (uptr)addr, size, false);
120}
121
122void __tsan_write_range(void *addr, uptr size) {
123 MemoryAccessRange(cur_thread(), CALLERPC, (uptr)addr, size, true);
124}
125
126void __tsan_read_range_pc(void *addr, uptr size, void *pc) {
127 MemoryAccessRange(cur_thread(), (uptr)pc, (uptr)addr, size, false);
128}
129
130void __tsan_write_range_pc(void *addr, uptr size, void *pc) {
131 MemoryAccessRange(cur_thread(), (uptr)pc, (uptr)addr, size, true);
132}
lib/tsan/tsan_interface_java.cpp created+267
...@@ -0,0 +1,267 @@
1//===-- tsan_interface_java.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#include "tsan_interface_java.h"
14#include "tsan_rtl.h"
15#include "tsan_mutex.h"
16#include "sanitizer_common/sanitizer_internal_defs.h"
17#include "sanitizer_common/sanitizer_common.h"
18#include "sanitizer_common/sanitizer_placement_new.h"
19#include "sanitizer_common/sanitizer_stacktrace.h"
20#include "sanitizer_common/sanitizer_procmaps.h"
21
22using namespace __tsan;
23
24const jptr kHeapAlignment = 8;
25
26namespace __tsan {
27
28struct JavaContext {
29 const uptr heap_begin;
30 const uptr heap_size;
31
32 JavaContext(jptr heap_begin, jptr heap_size)
33 : heap_begin(heap_begin)
34 , heap_size(heap_size) {
35 }
36};
37
38class ScopedJavaFunc {
39 public:
40 ScopedJavaFunc(ThreadState *thr, uptr pc)
41 : thr_(thr) {
42 Initialize(thr_);
43 FuncEntry(thr, pc);
44 }
45
46 ~ScopedJavaFunc() {
47 FuncExit(thr_);
48 // FIXME(dvyukov): process pending signals.
49 }
50
51 private:
52 ThreadState *thr_;
53};
54
55static u64 jctx_buf[sizeof(JavaContext) / sizeof(u64) + 1];
56static JavaContext *jctx;
57
58} // namespace __tsan
59
60#define SCOPED_JAVA_FUNC(func) \
61 ThreadState *thr = cur_thread(); \
62 const uptr caller_pc = GET_CALLER_PC(); \
63 const uptr pc = StackTrace::GetCurrentPc(); \
64 (void)pc; \
65 ScopedJavaFunc scoped(thr, caller_pc); \
66/**/
67
68void __tsan_java_init(jptr heap_begin, jptr heap_size) {
69 SCOPED_JAVA_FUNC(__tsan_java_init);
70 DPrintf("#%d: java_init(%p, %p)\n", thr->tid, heap_begin, heap_size);
71 CHECK_EQ(jctx, 0);
72 CHECK_GT(heap_begin, 0);
73 CHECK_GT(heap_size, 0);
74 CHECK_EQ(heap_begin % kHeapAlignment, 0);
75 CHECK_EQ(heap_size % kHeapAlignment, 0);
76 CHECK_LT(heap_begin, heap_begin + heap_size);
77 jctx = new(jctx_buf) JavaContext(heap_begin, heap_size);
78}
79
80int __tsan_java_fini() {
81 SCOPED_JAVA_FUNC(__tsan_java_fini);
82 DPrintf("#%d: java_fini()\n", thr->tid);
83 CHECK_NE(jctx, 0);
84 // FIXME(dvyukov): this does not call atexit() callbacks.
85 int status = Finalize(thr);
86 DPrintf("#%d: java_fini() = %d\n", thr->tid, status);
87 return status;
88}
89
90void __tsan_java_alloc(jptr ptr, jptr size) {
91 SCOPED_JAVA_FUNC(__tsan_java_alloc);
92 DPrintf("#%d: java_alloc(%p, %p)\n", thr->tid, ptr, size);
93 CHECK_NE(jctx, 0);
94 CHECK_NE(size, 0);
95 CHECK_EQ(ptr % kHeapAlignment, 0);
96 CHECK_EQ(size % kHeapAlignment, 0);
97 CHECK_GE(ptr, jctx->heap_begin);
98 CHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
99
100 OnUserAlloc(thr, pc, ptr, size, false);
101}
102
103void __tsan_java_free(jptr ptr, jptr size) {
104 SCOPED_JAVA_FUNC(__tsan_java_free);
105 DPrintf("#%d: java_free(%p, %p)\n", thr->tid, ptr, size);
106 CHECK_NE(jctx, 0);
107 CHECK_NE(size, 0);
108 CHECK_EQ(ptr % kHeapAlignment, 0);
109 CHECK_EQ(size % kHeapAlignment, 0);
110 CHECK_GE(ptr, jctx->heap_begin);
111 CHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
112
113 ctx->metamap.FreeRange(thr->proc(), ptr, size);
114}
115
116void __tsan_java_move(jptr src, jptr dst, jptr size) {
117 SCOPED_JAVA_FUNC(__tsan_java_move);
118 DPrintf("#%d: java_move(%p, %p, %p)\n", thr->tid, src, dst, size);
119 CHECK_NE(jctx, 0);
120 CHECK_NE(size, 0);
121 CHECK_EQ(src % kHeapAlignment, 0);
122 CHECK_EQ(dst % kHeapAlignment, 0);
123 CHECK_EQ(size % kHeapAlignment, 0);
124 CHECK_GE(src, jctx->heap_begin);
125 CHECK_LE(src + size, jctx->heap_begin + jctx->heap_size);
126 CHECK_GE(dst, jctx->heap_begin);
127 CHECK_LE(dst + size, jctx->heap_begin + jctx->heap_size);
128 CHECK_NE(dst, src);
129 CHECK_NE(size, 0);
130
131 // Assuming it's not running concurrently with threads that do
132 // memory accesses and mutex operations (stop-the-world phase).
133 ctx->metamap.MoveMemory(src, dst, size);
134
135 // Move shadow.
136 u64 *s = (u64*)MemToShadow(src);
137 u64 *d = (u64*)MemToShadow(dst);
138 u64 *send = (u64*)MemToShadow(src + size);
139 uptr inc = 1;
140 if (dst > src) {
141 s = (u64*)MemToShadow(src + size) - 1;
142 d = (u64*)MemToShadow(dst + size) - 1;
143 send = (u64*)MemToShadow(src) - 1;
144 inc = -1;
145 }
146 for (; s != send; s += inc, d += inc) {
147 *d = *s;
148 *s = 0;
149 }
150}
151
152jptr __tsan_java_find(jptr *from_ptr, jptr to) {
153 SCOPED_JAVA_FUNC(__tsan_java_find);
154 DPrintf("#%d: java_find(&%p, %p)\n", *from_ptr, to);
155 CHECK_EQ((*from_ptr) % kHeapAlignment, 0);
156 CHECK_EQ(to % kHeapAlignment, 0);
157 CHECK_GE(*from_ptr, jctx->heap_begin);
158 CHECK_LE(to, jctx->heap_begin + jctx->heap_size);
159 for (uptr from = *from_ptr; from < to; from += kHeapAlignment) {
160 MBlock *b = ctx->metamap.GetBlock(from);
161 if (b) {
162 *from_ptr = from;
163 return b->siz;
164 }
165 }
166 return 0;
167}
168
169void __tsan_java_finalize() {
170 SCOPED_JAVA_FUNC(__tsan_java_finalize);
171 DPrintf("#%d: java_mutex_finalize()\n", thr->tid);
172 AcquireGlobal(thr, 0);
173}
174
175void __tsan_java_mutex_lock(jptr addr) {
176 SCOPED_JAVA_FUNC(__tsan_java_mutex_lock);
177 DPrintf("#%d: java_mutex_lock(%p)\n", thr->tid, addr);
178 CHECK_NE(jctx, 0);
179 CHECK_GE(addr, jctx->heap_begin);
180 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
181
182 MutexPostLock(thr, pc, addr, MutexFlagLinkerInit | MutexFlagWriteReentrant |
183 MutexFlagDoPreLockOnPostLock);
184}
185
186void __tsan_java_mutex_unlock(jptr addr) {
187 SCOPED_JAVA_FUNC(__tsan_java_mutex_unlock);
188 DPrintf("#%d: java_mutex_unlock(%p)\n", thr->tid, addr);
189 CHECK_NE(jctx, 0);
190 CHECK_GE(addr, jctx->heap_begin);
191 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
192
193 MutexUnlock(thr, pc, addr);
194}
195
196void __tsan_java_mutex_read_lock(jptr addr) {
197 SCOPED_JAVA_FUNC(__tsan_java_mutex_read_lock);
198 DPrintf("#%d: java_mutex_read_lock(%p)\n", thr->tid, addr);
199 CHECK_NE(jctx, 0);
200 CHECK_GE(addr, jctx->heap_begin);
201 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
202
203 MutexPostReadLock(thr, pc, addr, MutexFlagLinkerInit |
204 MutexFlagWriteReentrant | MutexFlagDoPreLockOnPostLock);
205}
206
207void __tsan_java_mutex_read_unlock(jptr addr) {
208 SCOPED_JAVA_FUNC(__tsan_java_mutex_read_unlock);
209 DPrintf("#%d: java_mutex_read_unlock(%p)\n", thr->tid, addr);
210 CHECK_NE(jctx, 0);
211 CHECK_GE(addr, jctx->heap_begin);
212 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
213
214 MutexReadUnlock(thr, pc, addr);
215}
216
217void __tsan_java_mutex_lock_rec(jptr addr, int rec) {
218 SCOPED_JAVA_FUNC(__tsan_java_mutex_lock_rec);
219 DPrintf("#%d: java_mutex_lock_rec(%p, %d)\n", thr->tid, addr, rec);
220 CHECK_NE(jctx, 0);
221 CHECK_GE(addr, jctx->heap_begin);
222 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
223 CHECK_GT(rec, 0);
224
225 MutexPostLock(thr, pc, addr, MutexFlagLinkerInit | MutexFlagWriteReentrant |
226 MutexFlagDoPreLockOnPostLock | MutexFlagRecursiveLock, rec);
227}
228
229int __tsan_java_mutex_unlock_rec(jptr addr) {
230 SCOPED_JAVA_FUNC(__tsan_java_mutex_unlock_rec);
231 DPrintf("#%d: java_mutex_unlock_rec(%p)\n", thr->tid, addr);
232 CHECK_NE(jctx, 0);
233 CHECK_GE(addr, jctx->heap_begin);
234 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
235
236 return MutexUnlock(thr, pc, addr, MutexFlagRecursiveUnlock);
237}
238
239void __tsan_java_acquire(jptr addr) {
240 SCOPED_JAVA_FUNC(__tsan_java_acquire);
241 DPrintf("#%d: java_acquire(%p)\n", thr->tid, addr);
242 CHECK_NE(jctx, 0);
243 CHECK_GE(addr, jctx->heap_begin);
244 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
245
246 Acquire(thr, caller_pc, addr);
247}
248
249void __tsan_java_release(jptr addr) {
250 SCOPED_JAVA_FUNC(__tsan_java_release);
251 DPrintf("#%d: java_release(%p)\n", thr->tid, addr);
252 CHECK_NE(jctx, 0);
253 CHECK_GE(addr, jctx->heap_begin);
254 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
255
256 Release(thr, caller_pc, addr);
257}
258
259void __tsan_java_release_store(jptr addr) {
260 SCOPED_JAVA_FUNC(__tsan_java_release);
261 DPrintf("#%d: java_release_store(%p)\n", thr->tid, addr);
262 CHECK_NE(jctx, 0);
263 CHECK_GE(addr, jctx->heap_begin);
264 CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
265
266 ReleaseStore(thr, caller_pc, addr);
267}
lib/tsan/tsan_interface_java.h created+99
...@@ -0,0 +1,99 @@
1//===-- tsan_interface_java.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// Interface for verification of Java or mixed Java/C++ programs.
12// The interface is intended to be used from within a JVM and notify TSan
13// about such events like Java locks and GC memory compaction.
14//
15// For plain memory accesses and function entry/exit a JVM is intended to use
16// C++ interfaces: __tsan_readN/writeN and __tsan_func_enter/exit.
17//
18// For volatile memory accesses and atomic operations JVM is intended to use
19// standard atomics API: __tsan_atomicN_load/store/etc.
20//
21// For usage examples see lit_tests/java_*.cpp
22//===----------------------------------------------------------------------===//
23#ifndef TSAN_INTERFACE_JAVA_H
24#define TSAN_INTERFACE_JAVA_H
25
26#ifndef INTERFACE_ATTRIBUTE
27# define INTERFACE_ATTRIBUTE __attribute__((visibility("default")))
28#endif
29
30#ifdef __cplusplus
31extern "C" {
32#endif
33
34typedef unsigned long jptr;
35
36// Must be called before any other callback from Java.
37void __tsan_java_init(jptr heap_begin, jptr heap_size) INTERFACE_ATTRIBUTE;
38// Must be called when the application exits.
39// Not necessary the last callback (concurrently running threads are OK).
40// Returns exit status or 0 if tsan does not want to override it.
41int __tsan_java_fini() INTERFACE_ATTRIBUTE;
42
43// Callback for memory allocations.
44// May be omitted for allocations that are not subject to data races
45// nor contain synchronization objects (e.g. String).
46void __tsan_java_alloc(jptr ptr, jptr size) INTERFACE_ATTRIBUTE;
47// Callback for memory free.
48// Can be aggregated for several objects (preferably).
49void __tsan_java_free(jptr ptr, jptr size) INTERFACE_ATTRIBUTE;
50// Callback for memory move by GC.
51// Can be aggregated for several objects (preferably).
52// The ranges can overlap.
53void __tsan_java_move(jptr src, jptr dst, jptr size) INTERFACE_ATTRIBUTE;
54// This function must be called on the finalizer thread
55// before executing a batch of finalizers.
56// It ensures necessary synchronization between
57// java object creation and finalization.
58void __tsan_java_finalize() INTERFACE_ATTRIBUTE;
59// Finds the first allocated memory block in the [*from_ptr, to) range, saves
60// its address in *from_ptr and returns its size. Returns 0 if there are no
61// allocated memory blocks in the range.
62jptr __tsan_java_find(jptr *from_ptr, jptr to) INTERFACE_ATTRIBUTE;
63
64// Mutex lock.
65// Addr is any unique address associated with the mutex.
66// Can be called on recursive reentry.
67void __tsan_java_mutex_lock(jptr addr) INTERFACE_ATTRIBUTE;
68// Mutex unlock.
69void __tsan_java_mutex_unlock(jptr addr) INTERFACE_ATTRIBUTE;
70// Mutex read lock.
71void __tsan_java_mutex_read_lock(jptr addr) INTERFACE_ATTRIBUTE;
72// Mutex read unlock.
73void __tsan_java_mutex_read_unlock(jptr addr) INTERFACE_ATTRIBUTE;
74// Recursive mutex lock, intended for handling of Object.wait().
75// The 'rec' value must be obtained from the previous
76// __tsan_java_mutex_unlock_rec().
77void __tsan_java_mutex_lock_rec(jptr addr, int rec) INTERFACE_ATTRIBUTE;
78// Recursive mutex unlock, intended for handling of Object.wait().
79// The return value says how many times this thread called lock()
80// w/o a pairing unlock() (i.e. how many recursive levels it unlocked).
81// It must be passed back to __tsan_java_mutex_lock_rec() to restore
82// the same recursion level.
83int __tsan_java_mutex_unlock_rec(jptr addr) INTERFACE_ATTRIBUTE;
84
85// Raw acquire/release primitives.
86// Can be used to establish happens-before edges on volatile/final fields,
87// in atomic operations, etc. release_store is the same as release, but it
88// breaks release sequence on addr (see C++ standard 1.10/7 for details).
89void __tsan_java_acquire(jptr addr) INTERFACE_ATTRIBUTE;
90void __tsan_java_release(jptr addr) INTERFACE_ATTRIBUTE;
91void __tsan_java_release_store(jptr addr) INTERFACE_ATTRIBUTE;
92
93#ifdef __cplusplus
94} // extern "C"
95#endif
96
97#undef INTERFACE_ATTRIBUTE
98
99#endif // #ifndef TSAN_INTERFACE_JAVA_H
lib/tsan/tsan_malloc_mac.cpp created+71
...@@ -0,0 +1,71 @@
1//===-- tsan_malloc_mac.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// Mac-specific malloc interception.
12//===----------------------------------------------------------------------===//
13
14#include "sanitizer_common/sanitizer_platform.h"
15#if SANITIZER_MAC
16
17#include "sanitizer_common/sanitizer_errno.h"
18#include "tsan_interceptors.h"
19#include "tsan_stack_trace.h"
20
21using namespace __tsan;
22#define COMMON_MALLOC_ZONE_NAME "tsan"
23#define COMMON_MALLOC_ENTER()
24#define COMMON_MALLOC_SANITIZER_INITIALIZED (cur_thread()->is_inited)
25#define COMMON_MALLOC_FORCE_LOCK()
26#define COMMON_MALLOC_FORCE_UNLOCK()
27#define COMMON_MALLOC_MEMALIGN(alignment, size) \
28 void *p = \
29 user_memalign(cur_thread(), StackTrace::GetCurrentPc(), alignment, size)
30#define COMMON_MALLOC_MALLOC(size) \
31 if (in_symbolizer()) return InternalAlloc(size); \
32 SCOPED_INTERCEPTOR_RAW(malloc, size); \
33 void *p = user_alloc(thr, pc, size)
34#define COMMON_MALLOC_REALLOC(ptr, size) \
35 if (in_symbolizer()) return InternalRealloc(ptr, size); \
36 SCOPED_INTERCEPTOR_RAW(realloc, ptr, size); \
37 void *p = user_realloc(thr, pc, ptr, size)
38#define COMMON_MALLOC_CALLOC(count, size) \
39 if (in_symbolizer()) return InternalCalloc(count, size); \
40 SCOPED_INTERCEPTOR_RAW(calloc, size, count); \
41 void *p = user_calloc(thr, pc, size, count)
42#define COMMON_MALLOC_POSIX_MEMALIGN(memptr, alignment, size) \
43 if (in_symbolizer()) { \
44 void *p = InternalAlloc(size, nullptr, alignment); \
45 if (!p) return errno_ENOMEM; \
46 *memptr = p; \
47 return 0; \
48 } \
49 SCOPED_INTERCEPTOR_RAW(posix_memalign, memptr, alignment, size); \
50 int res = user_posix_memalign(thr, pc, memptr, alignment, size);
51#define COMMON_MALLOC_VALLOC(size) \
52 if (in_symbolizer()) \
53 return InternalAlloc(size, nullptr, GetPageSizeCached()); \
54 SCOPED_INTERCEPTOR_RAW(valloc, size); \
55 void *p = user_valloc(thr, pc, size)
56#define COMMON_MALLOC_FREE(ptr) \
57 if (in_symbolizer()) return InternalFree(ptr); \
58 SCOPED_INTERCEPTOR_RAW(free, ptr); \
59 user_free(thr, pc, ptr)
60#define COMMON_MALLOC_SIZE(ptr) uptr size = user_alloc_usable_size(ptr);
61#define COMMON_MALLOC_FILL_STATS(zone, stats)
62#define COMMON_MALLOC_REPORT_UNKNOWN_REALLOC(ptr, zone_ptr, zone_name) \
63 (void)zone_name; \
64 Report("mz_realloc(%p) -- attempting to realloc unallocated memory.\n", ptr);
65#define COMMON_MALLOC_NAMESPACE __tsan
66#define COMMON_MALLOC_HAS_ZONE_ENUMERATOR 0
67#define COMMON_MALLOC_HAS_EXTRA_INTROSPECTION_INIT 0
68
69#include "sanitizer_common/sanitizer_malloc_mac.inc"
70
71#endif
lib/tsan/tsan_md5.cpp created+250
...@@ -0,0 +1,250 @@
1//===-- tsan_md5.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_defs.h"
13
14namespace __tsan {
15
16#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
17#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
18#define H(x, y, z) ((x) ^ (y) ^ (z))
19#define I(x, y, z) ((y) ^ ((x) | ~(z)))
20
21#define STEP(f, a, b, c, d, x, t, s) \
22 (a) += f((b), (c), (d)) + (x) + (t); \
23 (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
24 (a) += (b);
25
26#define SET(n) \
27 (*(const MD5_u32plus *)&ptr[(n) * 4])
28#define GET(n) \
29 SET(n)
30
31typedef unsigned int MD5_u32plus;
32typedef unsigned long ulong_t;
33
34typedef struct {
35 MD5_u32plus lo, hi;
36 MD5_u32plus a, b, c, d;
37 unsigned char buffer[64];
38 MD5_u32plus block[16];
39} MD5_CTX;
40
41static const void *body(MD5_CTX *ctx, const void *data, ulong_t size) {
42 const unsigned char *ptr = (const unsigned char *)data;
43 MD5_u32plus a, b, c, d;
44 MD5_u32plus saved_a, saved_b, saved_c, saved_d;
45
46 a = ctx->a;
47 b = ctx->b;
48 c = ctx->c;
49 d = ctx->d;
50
51 do {
52 saved_a = a;
53 saved_b = b;
54 saved_c = c;
55 saved_d = d;
56
57 STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
58 STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
59 STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
60 STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
61 STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
62 STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
63 STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
64 STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
65 STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
66 STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
67 STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
68 STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
69 STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
70 STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
71 STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
72 STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
73
74 STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
75 STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
76 STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
77 STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
78 STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
79 STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
80 STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
81 STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
82 STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
83 STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
84 STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
85 STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
86 STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
87 STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
88 STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
89 STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
90
91 STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
92 STEP(H, d, a, b, c, GET(8), 0x8771f681, 11)
93 STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
94 STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23)
95 STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
96 STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11)
97 STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
98 STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23)
99 STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
100 STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11)
101 STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
102 STEP(H, b, c, d, a, GET(6), 0x04881d05, 23)
103 STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
104 STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11)
105 STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
106 STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23)
107
108 STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
109 STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
110 STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
111 STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
112 STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
113 STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
114 STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
115 STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
116 STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
117 STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
118 STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
119 STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
120 STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
121 STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
122 STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
123 STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
124
125 a += saved_a;
126 b += saved_b;
127 c += saved_c;
128 d += saved_d;
129
130 ptr += 64;
131 } while (size -= 64);
132
133 ctx->a = a;
134 ctx->b = b;
135 ctx->c = c;
136 ctx->d = d;
137
138 return ptr;
139}
140
141#undef F
142#undef G
143#undef H
144#undef I
145#undef STEP
146#undef SET
147#undef GET
148
149void MD5_Init(MD5_CTX *ctx) {
150 ctx->a = 0x67452301;
151 ctx->b = 0xefcdab89;
152 ctx->c = 0x98badcfe;
153 ctx->d = 0x10325476;
154
155 ctx->lo = 0;
156 ctx->hi = 0;
157}
158
159void MD5_Update(MD5_CTX *ctx, const void *data, ulong_t size) {
160 MD5_u32plus saved_lo;
161 ulong_t used, free;
162
163 saved_lo = ctx->lo;
164 if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
165 ctx->hi++;
166 ctx->hi += size >> 29;
167
168 used = saved_lo & 0x3f;
169
170 if (used) {
171 free = 64 - used;
172
173 if (size < free) {
174 internal_memcpy(&ctx->buffer[used], data, size);
175 return;
176 }
177
178 internal_memcpy(&ctx->buffer[used], data, free);
179 data = (const unsigned char *)data + free;
180 size -= free;
181 body(ctx, ctx->buffer, 64);
182 }
183
184 if (size >= 64) {
185 data = body(ctx, data, size & ~(ulong_t)0x3f);
186 size &= 0x3f;
187 }
188
189 internal_memcpy(ctx->buffer, data, size);
190}
191
192void MD5_Final(unsigned char *result, MD5_CTX *ctx) {
193 ulong_t used, free;
194
195 used = ctx->lo & 0x3f;
196
197 ctx->buffer[used++] = 0x80;
198
199 free = 64 - used;
200
201 if (free < 8) {
202 internal_memset(&ctx->buffer[used], 0, free);
203 body(ctx, ctx->buffer, 64);
204 used = 0;
205 free = 64;
206 }
207
208 internal_memset(&ctx->buffer[used], 0, free - 8);
209
210 ctx->lo <<= 3;
211 ctx->buffer[56] = ctx->lo;
212 ctx->buffer[57] = ctx->lo >> 8;
213 ctx->buffer[58] = ctx->lo >> 16;
214 ctx->buffer[59] = ctx->lo >> 24;
215 ctx->buffer[60] = ctx->hi;
216 ctx->buffer[61] = ctx->hi >> 8;
217 ctx->buffer[62] = ctx->hi >> 16;
218 ctx->buffer[63] = ctx->hi >> 24;
219
220 body(ctx, ctx->buffer, 64);
221
222 result[0] = ctx->a;
223 result[1] = ctx->a >> 8;
224 result[2] = ctx->a >> 16;
225 result[3] = ctx->a >> 24;
226 result[4] = ctx->b;
227 result[5] = ctx->b >> 8;
228 result[6] = ctx->b >> 16;
229 result[7] = ctx->b >> 24;
230 result[8] = ctx->c;
231 result[9] = ctx->c >> 8;
232 result[10] = ctx->c >> 16;
233 result[11] = ctx->c >> 24;
234 result[12] = ctx->d;
235 result[13] = ctx->d >> 8;
236 result[14] = ctx->d >> 16;
237 result[15] = ctx->d >> 24;
238
239 internal_memset(ctx, 0, sizeof(*ctx));
240}
241
242MD5Hash md5_hash(const void *data, uptr size) {
243 MD5Hash res;
244 MD5_CTX ctx;
245 MD5_Init(&ctx);
246 MD5_Update(&ctx, data, size);
247 MD5_Final((unsigned char*)&res.hash[0], &ctx);
248 return res;
249}
250} // namespace __tsan
lib/tsan/tsan_mman.cpp created+405
...@@ -0,0 +1,405 @@
1//===-- tsan_mman.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 "sanitizer_common/sanitizer_allocator_checks.h"
13#include "sanitizer_common/sanitizer_allocator_interface.h"
14#include "sanitizer_common/sanitizer_allocator_report.h"
15#include "sanitizer_common/sanitizer_common.h"
16#include "sanitizer_common/sanitizer_errno.h"
17#include "sanitizer_common/sanitizer_placement_new.h"
18#include "tsan_mman.h"
19#include "tsan_rtl.h"
20#include "tsan_report.h"
21#include "tsan_flags.h"
22
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
35namespace __tsan {
36
37struct MapUnmapCallback {
38 void OnMap(uptr p, uptr size) const { }
39 void OnUnmap(uptr p, uptr size) const {
40 // We are about to unmap a chunk of user memory.
41 // Mark the corresponding shadow memory as not needed.
42 DontNeedShadowFor(p, size);
43 // Mark the corresponding meta shadow memory as not needed.
44 // Note the block does not contain any meta info at this point
45 // (this happens after free).
46 const uptr kMetaRatio = kMetaShadowCell / kMetaShadowSize;
47 const uptr kPageSize = GetPageSizeCached() * kMetaRatio;
48 // Block came from LargeMmapAllocator, so must be large.
49 // We rely on this in the calculations below.
50 CHECK_GE(size, 2 * kPageSize);
51 uptr diff = RoundUp(p, kPageSize) - p;
52 if (diff != 0) {
53 p += diff;
54 size -= diff;
55 }
56 diff = p + size - RoundDown(p + size, kPageSize);
57 if (diff != 0)
58 size -= diff;
59 uptr p_meta = (uptr)MemToMeta(p);
60 ReleaseMemoryPagesToOS(p_meta, p_meta + size / kMetaRatio);
61 }
62};
63
64static char allocator_placeholder[sizeof(Allocator)] ALIGNED(64);
65Allocator *allocator() {
66 return reinterpret_cast<Allocator*>(&allocator_placeholder);
67}
68
69struct GlobalProc {
70 Mutex mtx;
71 Processor *proc;
72
73 GlobalProc()
74 : mtx(MutexTypeGlobalProc, StatMtxGlobalProc)
75 , proc(ProcCreate()) {
76 }
77};
78
79static char global_proc_placeholder[sizeof(GlobalProc)] ALIGNED(64);
80GlobalProc *global_proc() {
81 return reinterpret_cast<GlobalProc*>(&global_proc_placeholder);
82}
83
84ScopedGlobalProcessor::ScopedGlobalProcessor() {
85 GlobalProc *gp = global_proc();
86 ThreadState *thr = cur_thread();
87 if (thr->proc())
88 return;
89 // If we don't have a proc, use the global one.
90 // There are currently only two known case where this path is triggered:
91 // __interceptor_free
92 // __nptl_deallocate_tsd
93 // start_thread
94 // clone
95 // and:
96 // ResetRange
97 // __interceptor_munmap
98 // __deallocate_stack
99 // start_thread
100 // clone
101 // Ideally, we destroy thread state (and unwire proc) when a thread actually
102 // exits (i.e. when we join/wait it). Then we would not need the global proc
103 gp->mtx.Lock();
104 ProcWire(gp->proc, thr);
105}
106
107ScopedGlobalProcessor::~ScopedGlobalProcessor() {
108 GlobalProc *gp = global_proc();
109 ThreadState *thr = cur_thread();
110 if (thr->proc() != gp->proc)
111 return;
112 ProcUnwire(gp->proc, thr);
113 gp->mtx.Unlock();
114}
115
116static constexpr uptr kMaxAllowedMallocSize = 1ull << 40;
117static uptr max_user_defined_malloc_size;
118
119void InitializeAllocator() {
120 SetAllocatorMayReturnNull(common_flags()->allocator_may_return_null);
121 allocator()->Init(common_flags()->allocator_release_to_os_interval_ms);
122 max_user_defined_malloc_size = common_flags()->max_allocation_size_mb
123 ? common_flags()->max_allocation_size_mb
124 << 20
125 : kMaxAllowedMallocSize;
126}
127
128void InitializeAllocatorLate() {
129 new(global_proc()) GlobalProc();
130}
131
132void AllocatorProcStart(Processor *proc) {
133 allocator()->InitCache(&proc->alloc_cache);
134 internal_allocator()->InitCache(&proc->internal_alloc_cache);
135}
136
137void AllocatorProcFinish(Processor *proc) {
138 allocator()->DestroyCache(&proc->alloc_cache);
139 internal_allocator()->DestroyCache(&proc->internal_alloc_cache);
140}
141
142void AllocatorPrintStats() {
143 allocator()->PrintStats();
144}
145
146static void SignalUnsafeCall(ThreadState *thr, uptr pc) {
147 if (atomic_load_relaxed(&thr->in_signal_handler) == 0 ||
148 !flags()->report_signal_unsafe)
149 return;
150 VarSizeStackTrace stack;
151 ObtainCurrentStack(thr, pc, &stack);
152 if (IsFiredSuppression(ctx, ReportTypeSignalUnsafe, stack))
153 return;
154 ThreadRegistryLock l(ctx->thread_registry);
155 ScopedReport rep(ReportTypeSignalUnsafe);
156 rep.AddStack(stack, true);
157 OutputReport(thr, rep);
158}
159
160
161void *user_alloc_internal(ThreadState *thr, uptr pc, uptr sz, uptr align,
162 bool signal) {
163 if (sz >= kMaxAllowedMallocSize || align >= kMaxAllowedMallocSize ||
164 sz > max_user_defined_malloc_size) {
165 if (AllocatorMayReturnNull())
166 return nullptr;
167 uptr malloc_limit =
168 Min(kMaxAllowedMallocSize, max_user_defined_malloc_size);
169 GET_STACK_TRACE_FATAL(thr, pc);
170 ReportAllocationSizeTooBig(sz, malloc_limit, &stack);
171 }
172 void *p = allocator()->Allocate(&thr->proc()->alloc_cache, sz, align);
173 if (UNLIKELY(!p)) {
174 SetAllocatorOutOfMemory();
175 if (AllocatorMayReturnNull())
176 return nullptr;
177 GET_STACK_TRACE_FATAL(thr, pc);
178 ReportOutOfMemory(sz, &stack);
179 }
180 if (ctx && ctx->initialized)
181 OnUserAlloc(thr, pc, (uptr)p, sz, true);
182 if (signal)
183 SignalUnsafeCall(thr, pc);
184 return p;
185}
186
187void user_free(ThreadState *thr, uptr pc, void *p, bool signal) {
188 ScopedGlobalProcessor sgp;
189 if (ctx && ctx->initialized)
190 OnUserFree(thr, pc, (uptr)p, true);
191 allocator()->Deallocate(&thr->proc()->alloc_cache, p);
192 if (signal)
193 SignalUnsafeCall(thr, pc);
194}
195
196void *user_alloc(ThreadState *thr, uptr pc, uptr sz) {
197 return SetErrnoOnNull(user_alloc_internal(thr, pc, sz, kDefaultAlignment));
198}
199
200void *user_calloc(ThreadState *thr, uptr pc, uptr size, uptr n) {
201 if (UNLIKELY(CheckForCallocOverflow(size, n))) {
202 if (AllocatorMayReturnNull())
203 return SetErrnoOnNull(nullptr);
204 GET_STACK_TRACE_FATAL(thr, pc);
205 ReportCallocOverflow(n, size, &stack);
206 }
207 void *p = user_alloc_internal(thr, pc, n * size);
208 if (p)
209 internal_memset(p, 0, n * size);
210 return SetErrnoOnNull(p);
211}
212
213void *user_reallocarray(ThreadState *thr, uptr pc, void *p, uptr size, uptr n) {
214 if (UNLIKELY(CheckForCallocOverflow(size, n))) {
215 if (AllocatorMayReturnNull())
216 return SetErrnoOnNull(nullptr);
217 GET_STACK_TRACE_FATAL(thr, pc);
218 ReportReallocArrayOverflow(size, n, &stack);
219 }
220 return user_realloc(thr, pc, p, size * n);
221}
222
223void OnUserAlloc(ThreadState *thr, uptr pc, uptr p, uptr sz, bool write) {
224 DPrintf("#%d: alloc(%zu) = %p\n", thr->tid, sz, p);
225 ctx->metamap.AllocBlock(thr, pc, p, sz);
226 if (write && thr->ignore_reads_and_writes == 0)
227 MemoryRangeImitateWrite(thr, pc, (uptr)p, sz);
228 else
229 MemoryResetRange(thr, pc, (uptr)p, sz);
230}
231
232void OnUserFree(ThreadState *thr, uptr pc, uptr p, bool write) {
233 CHECK_NE(p, (void*)0);
234 uptr sz = ctx->metamap.FreeBlock(thr->proc(), p);
235 DPrintf("#%d: free(%p, %zu)\n", thr->tid, p, sz);
236 if (write && thr->ignore_reads_and_writes == 0)
237 MemoryRangeFreed(thr, pc, (uptr)p, sz);
238}
239
240void *user_realloc(ThreadState *thr, uptr pc, void *p, uptr sz) {
241 // FIXME: Handle "shrinking" more efficiently,
242 // it seems that some software actually does this.
243 if (!p)
244 return SetErrnoOnNull(user_alloc_internal(thr, pc, sz));
245 if (!sz) {
246 user_free(thr, pc, p);
247 return nullptr;
248 }
249 void *new_p = user_alloc_internal(thr, pc, sz);
250 if (new_p) {
251 uptr old_sz = user_alloc_usable_size(p);
252 internal_memcpy(new_p, p, min(old_sz, sz));
253 user_free(thr, pc, p);
254 }
255 return SetErrnoOnNull(new_p);
256}
257
258void *user_memalign(ThreadState *thr, uptr pc, uptr align, uptr sz) {
259 if (UNLIKELY(!IsPowerOfTwo(align))) {
260 errno = errno_EINVAL;
261 if (AllocatorMayReturnNull())
262 return nullptr;
263 GET_STACK_TRACE_FATAL(thr, pc);
264 ReportInvalidAllocationAlignment(align, &stack);
265 }
266 return SetErrnoOnNull(user_alloc_internal(thr, pc, sz, align));
267}
268
269int user_posix_memalign(ThreadState *thr, uptr pc, void **memptr, uptr align,
270 uptr sz) {
271 if (UNLIKELY(!CheckPosixMemalignAlignment(align))) {
272 if (AllocatorMayReturnNull())
273 return errno_EINVAL;
274 GET_STACK_TRACE_FATAL(thr, pc);
275 ReportInvalidPosixMemalignAlignment(align, &stack);
276 }
277 void *ptr = user_alloc_internal(thr, pc, sz, align);
278 if (UNLIKELY(!ptr))
279 // OOM error is already taken care of by user_alloc_internal.
280 return errno_ENOMEM;
281 CHECK(IsAligned((uptr)ptr, align));
282 *memptr = ptr;
283 return 0;
284}
285
286void *user_aligned_alloc(ThreadState *thr, uptr pc, uptr align, uptr sz) {
287 if (UNLIKELY(!CheckAlignedAllocAlignmentAndSize(align, sz))) {
288 errno = errno_EINVAL;
289 if (AllocatorMayReturnNull())
290 return nullptr;
291 GET_STACK_TRACE_FATAL(thr, pc);
292 ReportInvalidAlignedAllocAlignment(sz, align, &stack);
293 }
294 return SetErrnoOnNull(user_alloc_internal(thr, pc, sz, align));
295}
296
297void *user_valloc(ThreadState *thr, uptr pc, uptr sz) {
298 return SetErrnoOnNull(user_alloc_internal(thr, pc, sz, GetPageSizeCached()));
299}
300
301void *user_pvalloc(ThreadState *thr, uptr pc, uptr sz) {
302 uptr PageSize = GetPageSizeCached();
303 if (UNLIKELY(CheckForPvallocOverflow(sz, PageSize))) {
304 errno = errno_ENOMEM;
305 if (AllocatorMayReturnNull())
306 return nullptr;
307 GET_STACK_TRACE_FATAL(thr, pc);
308 ReportPvallocOverflow(sz, &stack);
309 }
310 // pvalloc(0) should allocate one page.
311 sz = sz ? RoundUpTo(sz, PageSize) : PageSize;
312 return SetErrnoOnNull(user_alloc_internal(thr, pc, sz, PageSize));
313}
314
315uptr user_alloc_usable_size(const void *p) {
316 if (p == 0)
317 return 0;
318 MBlock *b = ctx->metamap.GetBlock((uptr)p);
319 if (!b)
320 return 0; // Not a valid pointer.
321 if (b->siz == 0)
322 return 1; // Zero-sized allocations are actually 1 byte.
323 return b->siz;
324}
325
326void invoke_malloc_hook(void *ptr, uptr size) {
327 ThreadState *thr = cur_thread();
328 if (ctx == 0 || !ctx->initialized || thr->ignore_interceptors)
329 return;
330 __sanitizer_malloc_hook(ptr, size);
331 RunMallocHooks(ptr, size);
332}
333
334void invoke_free_hook(void *ptr) {
335 ThreadState *thr = cur_thread();
336 if (ctx == 0 || !ctx->initialized || thr->ignore_interceptors)
337 return;
338 __sanitizer_free_hook(ptr);
339 RunFreeHooks(ptr);
340}
341
342void *internal_alloc(MBlockType typ, uptr sz) {
343 ThreadState *thr = cur_thread();
344 if (thr->nomalloc) {
345 thr->nomalloc = 0; // CHECK calls internal_malloc().
346 CHECK(0);
347 }
348 return InternalAlloc(sz, &thr->proc()->internal_alloc_cache);
349}
350
351void internal_free(void *p) {
352 ThreadState *thr = cur_thread();
353 if (thr->nomalloc) {
354 thr->nomalloc = 0; // CHECK calls internal_malloc().
355 CHECK(0);
356 }
357 InternalFree(p, &thr->proc()->internal_alloc_cache);
358}
359
360} // namespace __tsan
361
362using namespace __tsan;
363
364extern "C" {
365uptr __sanitizer_get_current_allocated_bytes() {
366 uptr stats[AllocatorStatCount];
367 allocator()->GetStats(stats);
368 return stats[AllocatorStatAllocated];
369}
370
371uptr __sanitizer_get_heap_size() {
372 uptr stats[AllocatorStatCount];
373 allocator()->GetStats(stats);
374 return stats[AllocatorStatMapped];
375}
376
377uptr __sanitizer_get_free_bytes() {
378 return 1;
379}
380
381uptr __sanitizer_get_unmapped_bytes() {
382 return 1;
383}
384
385uptr __sanitizer_get_estimated_allocated_size(uptr size) {
386 return size;
387}
388
389int __sanitizer_get_ownership(const void *p) {
390 return allocator()->GetBlockBegin(p) != 0;
391}
392
393uptr __sanitizer_get_allocated_size(const void *p) {
394 return user_alloc_usable_size(p);
395}
396
397void __tsan_on_thread_idle() {
398 ThreadState *thr = cur_thread();
399 thr->clock.ResetCached(&thr->proc()->clock_cache);
400 thr->last_sleep_clock.ResetCached(&thr->proc()->clock_cache);
401 allocator()->SwallowCache(&thr->proc()->alloc_cache);
402 internal_allocator()->SwallowCache(&thr->proc()->internal_alloc_cache);
403 ctx->metamap.OnProcIdle(thr->proc());
404}
405} // extern "C"
lib/tsan/tsan_mman.h created+89
...@@ -0,0 +1,89 @@
1//===-- tsan_mman.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_MMAN_H
13#define TSAN_MMAN_H
14
15#include "tsan_defs.h"
16
17namespace __tsan {
18
19const uptr kDefaultAlignment = 16;
20
21void InitializeAllocator();
22void InitializeAllocatorLate();
23void ReplaceSystemMalloc();
24void AllocatorProcStart(Processor *proc);
25void AllocatorProcFinish(Processor *proc);
26void AllocatorPrintStats();
27
28// For user allocations.
29void *user_alloc_internal(ThreadState *thr, uptr pc, uptr sz,
30 uptr align = kDefaultAlignment, bool signal = true);
31// Does not accept NULL.
32void user_free(ThreadState *thr, uptr pc, void *p, bool signal = true);
33// Interceptor implementations.
34void *user_alloc(ThreadState *thr, uptr pc, uptr sz);
35void *user_calloc(ThreadState *thr, uptr pc, uptr sz, uptr n);
36void *user_realloc(ThreadState *thr, uptr pc, void *p, uptr sz);
37void *user_reallocarray(ThreadState *thr, uptr pc, void *p, uptr sz, uptr n);
38void *user_memalign(ThreadState *thr, uptr pc, uptr align, uptr sz);
39int user_posix_memalign(ThreadState *thr, uptr pc, void **memptr, uptr align,
40 uptr sz);
41void *user_aligned_alloc(ThreadState *thr, uptr pc, uptr align, uptr sz);
42void *user_valloc(ThreadState *thr, uptr pc, uptr sz);
43void *user_pvalloc(ThreadState *thr, uptr pc, uptr sz);
44uptr user_alloc_usable_size(const void *p);
45
46// Invoking malloc/free hooks that may be installed by the user.
47void invoke_malloc_hook(void *ptr, uptr size);
48void invoke_free_hook(void *ptr);
49
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,
73
74 // This must be the last.
75 MBlockTypeCount
76};
77
78// For internal data structures.
79void *internal_alloc(MBlockType typ, uptr sz);
80void internal_free(void *p);
81
82template <typename T>
83void DestroyAndFree(T *p) {
84 p->~T();
85 internal_free(p);
86}
87
88} // namespace __tsan
89#endif // TSAN_MMAN_H
lib/tsan/tsan_mutex.cpp created+289
...@@ -0,0 +1,289 @@
1//===-- tsan_mutex.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 "sanitizer_common/sanitizer_libc.h"
13#include "tsan_mutex.h"
14#include "tsan_platform.h"
15#include "tsan_rtl.h"
16
17namespace __tsan {
18
19// Simple reader-writer spin-mutex. Optimized for not-so-contended case.
20// Readers have preference, can possibly starvate writers.
21
22// The table fixes what mutexes can be locked under what mutexes.
23// E.g. if the row for MutexTypeThreads contains MutexTypeReport,
24// then Report mutex can be locked while under Threads mutex.
25// The leaf mutexes can be locked under any other mutexes.
26// Recursive locking is not supported.
27#if SANITIZER_DEBUG && !SANITIZER_GO
28const MutexType MutexTypeLeaf = (MutexType)-1;
29static MutexType CanLockTab[MutexTypeCount][MutexTypeCount] = {
30 /*0 MutexTypeInvalid*/ {},
31 /*1 MutexTypeTrace*/ {MutexTypeLeaf},
32 /*2 MutexTypeThreads*/ {MutexTypeReport},
33 /*3 MutexTypeReport*/ {MutexTypeSyncVar,
34 MutexTypeMBlock, MutexTypeJavaMBlock},
35 /*4 MutexTypeSyncVar*/ {MutexTypeDDetector},
36 /*5 MutexTypeSyncTab*/ {}, // unused
37 /*6 MutexTypeSlab*/ {MutexTypeLeaf},
38 /*7 MutexTypeAnnotations*/ {},
39 /*8 MutexTypeAtExit*/ {MutexTypeSyncVar},
40 /*9 MutexTypeMBlock*/ {MutexTypeSyncVar},
41 /*10 MutexTypeJavaMBlock*/ {MutexTypeSyncVar},
42 /*11 MutexTypeDDetector*/ {},
43 /*12 MutexTypeFired*/ {MutexTypeLeaf},
44 /*13 MutexTypeRacy*/ {MutexTypeLeaf},
45 /*14 MutexTypeGlobalProc*/ {},
46};
47
48static bool CanLockAdj[MutexTypeCount][MutexTypeCount];
49#endif
50
51void InitializeMutex() {
52#if SANITIZER_DEBUG && !SANITIZER_GO
53 // Build the "can lock" adjacency matrix.
54 // If [i][j]==true, then one can lock mutex j while under mutex i.
55 const int N = MutexTypeCount;
56 int cnt[N] = {};
57 bool leaf[N] = {};
58 for (int i = 1; i < N; i++) {
59 for (int j = 0; j < N; j++) {
60 MutexType z = CanLockTab[i][j];
61 if (z == MutexTypeInvalid)
62 continue;
63 if (z == MutexTypeLeaf) {
64 CHECK(!leaf[i]);
65 leaf[i] = true;
66 continue;
67 }
68 CHECK(!CanLockAdj[i][(int)z]);
69 CanLockAdj[i][(int)z] = true;
70 cnt[i]++;
71 }
72 }
73 for (int i = 0; i < N; i++) {
74 CHECK(!leaf[i] || cnt[i] == 0);
75 }
76 // Add leaf mutexes.
77 for (int i = 0; i < N; i++) {
78 if (!leaf[i])
79 continue;
80 for (int j = 0; j < N; j++) {
81 if (i == j || leaf[j] || j == MutexTypeInvalid)
82 continue;
83 CHECK(!CanLockAdj[j][i]);
84 CanLockAdj[j][i] = true;
85 }
86 }
87 // Build the transitive closure.
88 bool CanLockAdj2[MutexTypeCount][MutexTypeCount];
89 for (int i = 0; i < N; i++) {
90 for (int j = 0; j < N; j++) {
91 CanLockAdj2[i][j] = CanLockAdj[i][j];
92 }
93 }
94 for (int k = 0; k < N; k++) {
95 for (int i = 0; i < N; i++) {
96 for (int j = 0; j < N; j++) {
97 if (CanLockAdj2[i][k] && CanLockAdj2[k][j]) {
98 CanLockAdj2[i][j] = true;
99 }
100 }
101 }
102 }
103#if 0
104 Printf("Can lock graph:\n");
105 for (int i = 0; i < N; i++) {
106 for (int j = 0; j < N; j++) {
107 Printf("%d ", CanLockAdj[i][j]);
108 }
109 Printf("\n");
110 }
111 Printf("Can lock graph closure:\n");
112 for (int i = 0; i < N; i++) {
113 for (int j = 0; j < N; j++) {
114 Printf("%d ", CanLockAdj2[i][j]);
115 }
116 Printf("\n");
117 }
118#endif
119 // Verify that the graph is acyclic.
120 for (int i = 0; i < N; i++) {
121 if (CanLockAdj2[i][i]) {
122 Printf("Mutex %d participates in a cycle\n", i);
123 Die();
124 }
125 }
126#endif
127}
128
129InternalDeadlockDetector::InternalDeadlockDetector() {
130 // Rely on zero initialization because some mutexes can be locked before ctor.
131}
132
133#if SANITIZER_DEBUG && !SANITIZER_GO
134void InternalDeadlockDetector::Lock(MutexType t) {
135 // Printf("LOCK %d @%zu\n", t, seq_ + 1);
136 CHECK_GT(t, MutexTypeInvalid);
137 CHECK_LT(t, MutexTypeCount);
138 u64 max_seq = 0;
139 u64 max_idx = MutexTypeInvalid;
140 for (int i = 0; i != MutexTypeCount; i++) {
141 if (locked_[i] == 0)
142 continue;
143 CHECK_NE(locked_[i], max_seq);
144 if (max_seq < locked_[i]) {
145 max_seq = locked_[i];
146 max_idx = i;
147 }
148 }
149 locked_[t] = ++seq_;
150 if (max_idx == MutexTypeInvalid)
151 return;
152 // Printf(" last %d @%zu\n", max_idx, max_seq);
153 if (!CanLockAdj[max_idx][t]) {
154 Printf("ThreadSanitizer: internal deadlock detected\n");
155 Printf("ThreadSanitizer: can't lock %d while under %zu\n",
156 t, (uptr)max_idx);
157 CHECK(0);
158 }
159}
160
161void InternalDeadlockDetector::Unlock(MutexType t) {
162 // Printf("UNLO %d @%zu #%zu\n", t, seq_, locked_[t]);
163 CHECK(locked_[t]);
164 locked_[t] = 0;
165}
166
167void InternalDeadlockDetector::CheckNoLocks() {
168 for (int i = 0; i != MutexTypeCount; i++) {
169 CHECK_EQ(locked_[i], 0);
170 }
171}
172#endif
173
174void CheckNoLocks(ThreadState *thr) {
175#if SANITIZER_DEBUG && !SANITIZER_GO
176 thr->internal_deadlock_detector.CheckNoLocks();
177#endif
178}
179
180const uptr kUnlocked = 0;
181const uptr kWriteLock = 1;
182const uptr kReadLock = 2;
183
184class Backoff {
185 public:
186 Backoff()
187 : iter_() {
188 }
189
190 bool Do() {
191 if (iter_++ < kActiveSpinIters)
192 proc_yield(kActiveSpinCnt);
193 else
194 internal_sched_yield();
195 return true;
196 }
197
198 u64 Contention() const {
199 u64 active = iter_ % kActiveSpinIters;
200 u64 passive = iter_ - active;
201 return active + 10 * passive;
202 }
203
204 private:
205 int iter_;
206 static const int kActiveSpinIters = 10;
207 static const int kActiveSpinCnt = 20;
208};
209
210Mutex::Mutex(MutexType type, StatType stat_type) {
211 CHECK_GT(type, MutexTypeInvalid);
212 CHECK_LT(type, MutexTypeCount);
213#if SANITIZER_DEBUG
214 type_ = type;
215#endif
216#if TSAN_COLLECT_STATS
217 stat_type_ = stat_type;
218#endif
219 atomic_store(&state_, kUnlocked, memory_order_relaxed);
220}
221
222Mutex::~Mutex() {
223 CHECK_EQ(atomic_load(&state_, memory_order_relaxed), kUnlocked);
224}
225
226void Mutex::Lock() {
227#if SANITIZER_DEBUG && !SANITIZER_GO
228 cur_thread()->internal_deadlock_detector.Lock(type_);
229#endif
230 uptr cmp = kUnlocked;
231 if (atomic_compare_exchange_strong(&state_, &cmp, kWriteLock,
232 memory_order_acquire))
233 return;
234 for (Backoff backoff; backoff.Do();) {
235 if (atomic_load(&state_, memory_order_relaxed) == kUnlocked) {
236 cmp = kUnlocked;
237 if (atomic_compare_exchange_weak(&state_, &cmp, kWriteLock,
238 memory_order_acquire)) {
239#if TSAN_COLLECT_STATS && !SANITIZER_GO
240 StatInc(cur_thread(), stat_type_, backoff.Contention());
241#endif
242 return;
243 }
244 }
245 }
246}
247
248void Mutex::Unlock() {
249 uptr prev = atomic_fetch_sub(&state_, kWriteLock, memory_order_release);
250 (void)prev;
251 DCHECK_NE(prev & kWriteLock, 0);
252#if SANITIZER_DEBUG && !SANITIZER_GO
253 cur_thread()->internal_deadlock_detector.Unlock(type_);
254#endif
255}
256
257void Mutex::ReadLock() {
258#if SANITIZER_DEBUG && !SANITIZER_GO
259 cur_thread()->internal_deadlock_detector.Lock(type_);
260#endif
261 uptr prev = atomic_fetch_add(&state_, kReadLock, memory_order_acquire);
262 if ((prev & kWriteLock) == 0)
263 return;
264 for (Backoff backoff; backoff.Do();) {
265 prev = atomic_load(&state_, memory_order_acquire);
266 if ((prev & kWriteLock) == 0) {
267#if TSAN_COLLECT_STATS && !SANITIZER_GO
268 StatInc(cur_thread(), stat_type_, backoff.Contention());
269#endif
270 return;
271 }
272 }
273}
274
275void Mutex::ReadUnlock() {
276 uptr prev = atomic_fetch_sub(&state_, kReadLock, memory_order_release);
277 (void)prev;
278 DCHECK_EQ(prev & kWriteLock, 0);
279 DCHECK_GT(prev & ~kWriteLock, 0);
280#if SANITIZER_DEBUG && !SANITIZER_GO
281 cur_thread()->internal_deadlock_detector.Unlock(type_);
282#endif
283}
284
285void Mutex::CheckLocked() {
286 CHECK_NE(atomic_load(&state_, memory_order_relaxed), 0);
287}
288
289} // namespace __tsan
lib/tsan/tsan_mutex.h created+90
...@@ -0,0 +1,90 @@
1//===-- tsan_mutex.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_MUTEX_H
13#define TSAN_MUTEX_H
14
15#include "sanitizer_common/sanitizer_atomic.h"
16#include "sanitizer_common/sanitizer_mutex.h"
17#include "tsan_defs.h"
18
19namespace __tsan {
20
21enum MutexType {
22 MutexTypeInvalid,
23 MutexTypeTrace,
24 MutexTypeThreads,
25 MutexTypeReport,
26 MutexTypeSyncVar,
27 MutexTypeSyncTab,
28 MutexTypeSlab,
29 MutexTypeAnnotations,
30 MutexTypeAtExit,
31 MutexTypeMBlock,
32 MutexTypeJavaMBlock,
33 MutexTypeDDetector,
34 MutexTypeFired,
35 MutexTypeRacy,
36 MutexTypeGlobalProc,
37
38 // This must be the last.
39 MutexTypeCount
40};
41
42class Mutex {
43 public:
44 explicit Mutex(MutexType type, StatType stat_type);
45 ~Mutex();
46
47 void Lock();
48 void Unlock();
49
50 void ReadLock();
51 void ReadUnlock();
52
53 void CheckLocked();
54
55 private:
56 atomic_uintptr_t state_;
57#if SANITIZER_DEBUG
58 MutexType type_;
59#endif
60#if TSAN_COLLECT_STATS
61 StatType stat_type_;
62#endif
63
64 Mutex(const Mutex&);
65 void operator = (const Mutex&);
66};
67
68typedef GenericScopedLock<Mutex> Lock;
69typedef GenericScopedReadLock<Mutex> ReadLock;
70
71class InternalDeadlockDetector {
72 public:
73 InternalDeadlockDetector();
74 void Lock(MutexType t);
75 void Unlock(MutexType t);
76 void CheckNoLocks();
77 private:
78 u64 seq_;
79 u64 locked_[MutexTypeCount];
80};
81
82void InitializeMutex();
83
84// Checks that the current thread does not hold any runtime locks
85// (e.g. when returning from an interceptor).
86void CheckNoLocks(ThreadState *thr);
87
88} // namespace __tsan
89
90#endif // TSAN_MUTEX_H
lib/tsan/tsan_mutexset.cpp created+88
...@@ -0,0 +1,88 @@
1//===-- tsan_mutexset.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_mutexset.h"
13#include "tsan_rtl.h"
14
15namespace __tsan {
16
17const uptr MutexSet::kMaxSize;
18
19MutexSet::MutexSet() {
20 size_ = 0;
21 internal_memset(&descs_, 0, sizeof(descs_));
22}
23
24void MutexSet::Add(u64 id, bool write, u64 epoch) {
25 // Look up existing mutex with the same id.
26 for (uptr i = 0; i < size_; i++) {
27 if (descs_[i].id == id) {
28 descs_[i].count++;
29 descs_[i].epoch = epoch;
30 return;
31 }
32 }
33 // On overflow, find the oldest mutex and drop it.
34 if (size_ == kMaxSize) {
35 u64 minepoch = (u64)-1;
36 u64 mini = (u64)-1;
37 for (uptr i = 0; i < size_; i++) {
38 if (descs_[i].epoch < minepoch) {
39 minepoch = descs_[i].epoch;
40 mini = i;
41 }
42 }
43 RemovePos(mini);
44 CHECK_EQ(size_, kMaxSize - 1);
45 }
46 // Add new mutex descriptor.
47 descs_[size_].id = id;
48 descs_[size_].write = write;
49 descs_[size_].epoch = epoch;
50 descs_[size_].count = 1;
51 size_++;
52}
53
54void MutexSet::Del(u64 id, bool write) {
55 for (uptr i = 0; i < size_; i++) {
56 if (descs_[i].id == id) {
57 if (--descs_[i].count == 0)
58 RemovePos(i);
59 return;
60 }
61 }
62}
63
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
73void MutexSet::RemovePos(uptr i) {
74 CHECK_LT(i, size_);
75 descs_[i] = descs_[size_ - 1];
76 size_--;
77}
78
79uptr MutexSet::Size() const {
80 return size_;
81}
82
83MutexSet::Desc MutexSet::Get(uptr i) const {
84 CHECK_LT(i, size_);
85 return descs_[i];
86}
87
88} // namespace __tsan
lib/tsan/tsan_mutexset.h created+69
...@@ -0,0 +1,69 @@
1//===-- tsan_mutexset.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// MutexSet holds the set of mutexes currently held by a thread.
12//===----------------------------------------------------------------------===//
13#ifndef TSAN_MUTEXSET_H
14#define TSAN_MUTEXSET_H
15
16#include "tsan_defs.h"
17
18namespace __tsan {
19
20class MutexSet {
21 public:
22 // Holds limited number of mutexes.
23 // The oldest mutexes are discarded on overflow.
24 static const uptr kMaxSize = 16;
25 struct Desc {
26 u64 id;
27 u64 epoch;
28 int count;
29 bool write;
30 };
31
32 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).
37 uptr Size() const;
38 Desc Get(uptr i) const;
39
40 void operator=(const MutexSet &other) {
41 internal_memcpy(this, &other, sizeof(*this));
42 }
43
44 private:
45#if !SANITIZER_GO
46 uptr size_;
47 Desc descs_[kMaxSize];
48#endif
49
50 void RemovePos(uptr i);
51 MutexSet(const MutexSet&);
52};
53
54// Go does not have mutexes, so do not spend memory and time.
55// (Go sync.Mutex is actually a semaphore -- can be unlocked
56// in different goroutine).
57#if SANITIZER_GO
58MutexSet::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) {}
63uptr MutexSet::Size() const { return 0; }
64MutexSet::Desc MutexSet::Get(uptr i) const { return Desc(); }
65#endif
66
67} // namespace __tsan
68
69#endif // TSAN_MUTEXSET_H
lib/tsan/tsan_platform.h created+1028
...@@ -0,0 +1,1028 @@
1//===-- tsan_platform.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// Platform-specific code.
12//===----------------------------------------------------------------------===//
13
14#ifndef TSAN_PLATFORM_H
15#define TSAN_PLATFORM_H
16
17#if !defined(__LP64__) && !defined(_WIN64)
18# error "Only 64-bit is supported"
19#endif
20
21#include "tsan_defs.h"
22#include "tsan_trace.h"
23
24namespace __tsan {
25
26#if !SANITIZER_GO
27
28#if defined(__x86_64__)
29/*
30C/C++ on linux/x86_64 and freebsd/x86_64
310000 0000 1000 - 0080 0000 0000: main binary and/or MAP_32BIT mappings (512GB)
320040 0000 0000 - 0100 0000 0000: -
330100 0000 0000 - 2000 0000 0000: shadow
342000 0000 0000 - 3000 0000 0000: -
353000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects)
364000 0000 0000 - 5500 0000 0000: -
375500 0000 0000 - 5680 0000 0000: pie binaries without ASLR or on 4.1+ kernels
385680 0000 0000 - 6000 0000 0000: -
396000 0000 0000 - 6200 0000 0000: traces
406200 0000 0000 - 7d00 0000 0000: -
417b00 0000 0000 - 7c00 0000 0000: heap
427c00 0000 0000 - 7e80 0000 0000: -
437e80 0000 0000 - 8000 0000 0000: modules and main thread stack
44
45C/C++ on netbsd/amd64 can reuse the same mapping:
46 * The address space starts from 0x1000 (option with 0x0) and ends with
47 0x7f7ffffff000.
48 * LoAppMem-kHeapMemEnd can be reused as it is.
49 * No VDSO support.
50 * No MidAppMem region.
51 * No additional HeapMem region.
52 * HiAppMem contains the stack, loader, shared libraries and heap.
53 * Stack on NetBSD/amd64 has prereserved 128MB.
54 * Heap grows downwards (top-down).
55 * ASLR must be disabled per-process or globally.
56
57*/
58struct Mapping {
59 static const uptr kMetaShadowBeg = 0x300000000000ull;
60 static const uptr kMetaShadowEnd = 0x340000000000ull;
61 static const uptr kTraceMemBeg = 0x600000000000ull;
62 static const uptr kTraceMemEnd = 0x620000000000ull;
63 static const uptr kShadowBeg = 0x010000000000ull;
64 static const uptr kShadowEnd = 0x200000000000ull;
65 static const uptr kHeapMemBeg = 0x7b0000000000ull;
66 static const uptr kHeapMemEnd = 0x7c0000000000ull;
67 static const uptr kLoAppMemBeg = 0x000000001000ull;
68 static const uptr kLoAppMemEnd = 0x008000000000ull;
69 static const uptr kMidAppMemBeg = 0x550000000000ull;
70 static const uptr kMidAppMemEnd = 0x568000000000ull;
71 static const uptr kHiAppMemBeg = 0x7e8000000000ull;
72 static const uptr kHiAppMemEnd = 0x800000000000ull;
73 static const uptr kAppMemMsk = 0x780000000000ull;
74 static const uptr kAppMemXor = 0x040000000000ull;
75 static const uptr kVdsoBeg = 0xf000000000000000ull;
76};
77
78#define TSAN_MID_APP_RANGE 1
79#elif defined(__mips64)
80/*
81C/C++ on linux/mips64 (40-bit VMA)
820000 0000 00 - 0100 0000 00: - (4 GB)
830100 0000 00 - 0200 0000 00: main binary (4 GB)
840200 0000 00 - 2000 0000 00: - (120 GB)
852000 0000 00 - 4000 0000 00: shadow (128 GB)
864000 0000 00 - 5000 0000 00: metainfo (memory blocks and sync objects) (64 GB)
875000 0000 00 - aa00 0000 00: - (360 GB)
88aa00 0000 00 - ab00 0000 00: main binary (PIE) (4 GB)
89ab00 0000 00 - b000 0000 00: - (20 GB)
90b000 0000 00 - b200 0000 00: traces (8 GB)
91b200 0000 00 - fe00 0000 00: - (304 GB)
92fe00 0000 00 - ff00 0000 00: heap (4 GB)
93ff00 0000 00 - ff80 0000 00: - (2 GB)
94ff80 0000 00 - ffff ffff ff: modules and main thread stack (<2 GB)
95*/
96struct Mapping {
97 static const uptr kMetaShadowBeg = 0x4000000000ull;
98 static const uptr kMetaShadowEnd = 0x5000000000ull;
99 static const uptr kTraceMemBeg = 0xb000000000ull;
100 static const uptr kTraceMemEnd = 0xb200000000ull;
101 static const uptr kShadowBeg = 0x2000000000ull;
102 static const uptr kShadowEnd = 0x4000000000ull;
103 static const uptr kHeapMemBeg = 0xfe00000000ull;
104 static const uptr kHeapMemEnd = 0xff00000000ull;
105 static const uptr kLoAppMemBeg = 0x0100000000ull;
106 static const uptr kLoAppMemEnd = 0x0200000000ull;
107 static const uptr kMidAppMemBeg = 0xaa00000000ull;
108 static const uptr kMidAppMemEnd = 0xab00000000ull;
109 static const uptr kHiAppMemBeg = 0xff80000000ull;
110 static const uptr kHiAppMemEnd = 0xffffffffffull;
111 static const uptr kAppMemMsk = 0xf800000000ull;
112 static const uptr kAppMemXor = 0x0800000000ull;
113 static const uptr kVdsoBeg = 0xfffff00000ull;
114};
115
116#define TSAN_MID_APP_RANGE 1
117#elif defined(__aarch64__) && defined(__APPLE__)
118/*
119C/C++ on Darwin/iOS/ARM64 (36-bit VMA, 64 GB VM)
1200000 0000 00 - 0100 0000 00: - (4 GB)
1210100 0000 00 - 0200 0000 00: main binary, modules, thread stacks (4 GB)
1220200 0000 00 - 0300 0000 00: heap (4 GB)
1230300 0000 00 - 0400 0000 00: - (4 GB)
1240400 0000 00 - 0c00 0000 00: shadow memory (32 GB)
1250c00 0000 00 - 0d00 0000 00: - (4 GB)
1260d00 0000 00 - 0e00 0000 00: metainfo (4 GB)
1270e00 0000 00 - 0f00 0000 00: - (4 GB)
1280f00 0000 00 - 0fc0 0000 00: traces (3 GB)
1290fc0 0000 00 - 1000 0000 00: -
130*/
131struct Mapping {
132 static const uptr kLoAppMemBeg = 0x0100000000ull;
133 static const uptr kLoAppMemEnd = 0x0200000000ull;
134 static const uptr kHeapMemBeg = 0x0200000000ull;
135 static const uptr kHeapMemEnd = 0x0300000000ull;
136 static const uptr kShadowBeg = 0x0400000000ull;
137 static const uptr kShadowEnd = 0x0c00000000ull;
138 static const uptr kMetaShadowBeg = 0x0d00000000ull;
139 static const uptr kMetaShadowEnd = 0x0e00000000ull;
140 static const uptr kTraceMemBeg = 0x0f00000000ull;
141 static const uptr kTraceMemEnd = 0x0fc0000000ull;
142 static const uptr kHiAppMemBeg = 0x0fc0000000ull;
143 static const uptr kHiAppMemEnd = 0x0fc0000000ull;
144 static const uptr kAppMemMsk = 0x0ull;
145 static const uptr kAppMemXor = 0x0ull;
146 static const uptr kVdsoBeg = 0x7000000000000000ull;
147};
148
149#elif defined(__aarch64__)
150// AArch64 supports multiple VMA which leads to multiple address transformation
151// functions. To support these multiple VMAS transformations and mappings TSAN
152// runtime for AArch64 uses an external memory read (vmaSize) to select which
153// mapping to use. Although slower, it make a same instrumented binary run on
154// multiple kernels.
155
156/*
157C/C++ on linux/aarch64 (39-bit VMA)
1580000 0010 00 - 0100 0000 00: main binary
1590100 0000 00 - 0800 0000 00: -
1600800 0000 00 - 2000 0000 00: shadow memory
1612000 0000 00 - 3100 0000 00: -
1623100 0000 00 - 3400 0000 00: metainfo
1633400 0000 00 - 5500 0000 00: -
1645500 0000 00 - 5600 0000 00: main binary (PIE)
1655600 0000 00 - 6000 0000 00: -
1666000 0000 00 - 6200 0000 00: traces
1676200 0000 00 - 7d00 0000 00: -
1687c00 0000 00 - 7d00 0000 00: heap
1697d00 0000 00 - 7fff ffff ff: modules and main thread stack
170*/
171struct Mapping39 {
172 static const uptr kLoAppMemBeg = 0x0000001000ull;
173 static const uptr kLoAppMemEnd = 0x0100000000ull;
174 static const uptr kShadowBeg = 0x0800000000ull;
175 static const uptr kShadowEnd = 0x2000000000ull;
176 static const uptr kMetaShadowBeg = 0x3100000000ull;
177 static const uptr kMetaShadowEnd = 0x3400000000ull;
178 static const uptr kMidAppMemBeg = 0x5500000000ull;
179 static const uptr kMidAppMemEnd = 0x5600000000ull;
180 static const uptr kTraceMemBeg = 0x6000000000ull;
181 static const uptr kTraceMemEnd = 0x6200000000ull;
182 static const uptr kHeapMemBeg = 0x7c00000000ull;
183 static const uptr kHeapMemEnd = 0x7d00000000ull;
184 static const uptr kHiAppMemBeg = 0x7e00000000ull;
185 static const uptr kHiAppMemEnd = 0x7fffffffffull;
186 static const uptr kAppMemMsk = 0x7800000000ull;
187 static const uptr kAppMemXor = 0x0200000000ull;
188 static const uptr kVdsoBeg = 0x7f00000000ull;
189};
190
191/*
192C/C++ on linux/aarch64 (42-bit VMA)
19300000 0010 00 - 01000 0000 00: main binary
19401000 0000 00 - 10000 0000 00: -
19510000 0000 00 - 20000 0000 00: shadow memory
19620000 0000 00 - 26000 0000 00: -
19726000 0000 00 - 28000 0000 00: metainfo
19828000 0000 00 - 2aa00 0000 00: -
1992aa00 0000 00 - 2ab00 0000 00: main binary (PIE)
2002ab00 0000 00 - 36200 0000 00: -
20136200 0000 00 - 36240 0000 00: traces
20236240 0000 00 - 3e000 0000 00: -
2033e000 0000 00 - 3f000 0000 00: heap
2043f000 0000 00 - 3ffff ffff ff: modules and main thread stack
205*/
206struct Mapping42 {
207 static const uptr kLoAppMemBeg = 0x00000001000ull;
208 static const uptr kLoAppMemEnd = 0x01000000000ull;
209 static const uptr kShadowBeg = 0x10000000000ull;
210 static const uptr kShadowEnd = 0x20000000000ull;
211 static const uptr kMetaShadowBeg = 0x26000000000ull;
212 static const uptr kMetaShadowEnd = 0x28000000000ull;
213 static const uptr kMidAppMemBeg = 0x2aa00000000ull;
214 static const uptr kMidAppMemEnd = 0x2ab00000000ull;
215 static const uptr kTraceMemBeg = 0x36200000000ull;
216 static const uptr kTraceMemEnd = 0x36400000000ull;
217 static const uptr kHeapMemBeg = 0x3e000000000ull;
218 static const uptr kHeapMemEnd = 0x3f000000000ull;
219 static const uptr kHiAppMemBeg = 0x3f000000000ull;
220 static const uptr kHiAppMemEnd = 0x3ffffffffffull;
221 static const uptr kAppMemMsk = 0x3c000000000ull;
222 static const uptr kAppMemXor = 0x04000000000ull;
223 static const uptr kVdsoBeg = 0x37f00000000ull;
224};
225
226struct Mapping48 {
227 static const uptr kLoAppMemBeg = 0x0000000001000ull;
228 static const uptr kLoAppMemEnd = 0x0000200000000ull;
229 static const uptr kShadowBeg = 0x0002000000000ull;
230 static const uptr kShadowEnd = 0x0004000000000ull;
231 static const uptr kMetaShadowBeg = 0x0005000000000ull;
232 static const uptr kMetaShadowEnd = 0x0006000000000ull;
233 static const uptr kMidAppMemBeg = 0x0aaaa00000000ull;
234 static const uptr kMidAppMemEnd = 0x0aaaf00000000ull;
235 static const uptr kTraceMemBeg = 0x0f06000000000ull;
236 static const uptr kTraceMemEnd = 0x0f06200000000ull;
237 static const uptr kHeapMemBeg = 0x0ffff00000000ull;
238 static const uptr kHeapMemEnd = 0x0ffff00000000ull;
239 static const uptr kHiAppMemBeg = 0x0ffff00000000ull;
240 static const uptr kHiAppMemEnd = 0x1000000000000ull;
241 static const uptr kAppMemMsk = 0x0fff800000000ull;
242 static const uptr kAppMemXor = 0x0000800000000ull;
243 static const uptr kVdsoBeg = 0xffff000000000ull;
244};
245
246// Indicates the runtime will define the memory regions at runtime.
247#define TSAN_RUNTIME_VMA 1
248// Indicates that mapping defines a mid range memory segment.
249#define TSAN_MID_APP_RANGE 1
250#elif defined(__powerpc64__)
251// PPC64 supports multiple VMA which leads to multiple address transformation
252// functions. To support these multiple VMAS transformations and mappings TSAN
253// runtime for PPC64 uses an external memory read (vmaSize) to select which
254// mapping to use. Although slower, it make a same instrumented binary run on
255// multiple kernels.
256
257/*
258C/C++ on linux/powerpc64 (44-bit VMA)
2590000 0000 0100 - 0001 0000 0000: main binary
2600001 0000 0000 - 0001 0000 0000: -
2610001 0000 0000 - 0b00 0000 0000: shadow
2620b00 0000 0000 - 0b00 0000 0000: -
2630b00 0000 0000 - 0d00 0000 0000: metainfo (memory blocks and sync objects)
2640d00 0000 0000 - 0d00 0000 0000: -
2650d00 0000 0000 - 0f00 0000 0000: traces
2660f00 0000 0000 - 0f00 0000 0000: -
2670f00 0000 0000 - 0f50 0000 0000: heap
2680f50 0000 0000 - 0f60 0000 0000: -
2690f60 0000 0000 - 1000 0000 0000: modules and main thread stack
270*/
271struct Mapping44 {
272 static const uptr kMetaShadowBeg = 0x0b0000000000ull;
273 static const uptr kMetaShadowEnd = 0x0d0000000000ull;
274 static const uptr kTraceMemBeg = 0x0d0000000000ull;
275 static const uptr kTraceMemEnd = 0x0f0000000000ull;
276 static const uptr kShadowBeg = 0x000100000000ull;
277 static const uptr kShadowEnd = 0x0b0000000000ull;
278 static const uptr kLoAppMemBeg = 0x000000000100ull;
279 static const uptr kLoAppMemEnd = 0x000100000000ull;
280 static const uptr kHeapMemBeg = 0x0f0000000000ull;
281 static const uptr kHeapMemEnd = 0x0f5000000000ull;
282 static const uptr kHiAppMemBeg = 0x0f6000000000ull;
283 static const uptr kHiAppMemEnd = 0x100000000000ull; // 44 bits
284 static const uptr kAppMemMsk = 0x0f0000000000ull;
285 static const uptr kAppMemXor = 0x002100000000ull;
286 static const uptr kVdsoBeg = 0x3c0000000000000ull;
287};
288
289/*
290C/C++ on linux/powerpc64 (46-bit VMA)
2910000 0000 1000 - 0100 0000 0000: main binary
2920100 0000 0000 - 0200 0000 0000: -
2930100 0000 0000 - 1000 0000 0000: shadow
2941000 0000 0000 - 1000 0000 0000: -
2951000 0000 0000 - 2000 0000 0000: metainfo (memory blocks and sync objects)
2962000 0000 0000 - 2000 0000 0000: -
2972000 0000 0000 - 2200 0000 0000: traces
2982200 0000 0000 - 3d00 0000 0000: -
2993d00 0000 0000 - 3e00 0000 0000: heap
3003e00 0000 0000 - 3e80 0000 0000: -
3013e80 0000 0000 - 4000 0000 0000: modules and main thread stack
302*/
303struct Mapping46 {
304 static const uptr kMetaShadowBeg = 0x100000000000ull;
305 static const uptr kMetaShadowEnd = 0x200000000000ull;
306 static const uptr kTraceMemBeg = 0x200000000000ull;
307 static const uptr kTraceMemEnd = 0x220000000000ull;
308 static const uptr kShadowBeg = 0x010000000000ull;
309 static const uptr kShadowEnd = 0x100000000000ull;
310 static const uptr kHeapMemBeg = 0x3d0000000000ull;
311 static const uptr kHeapMemEnd = 0x3e0000000000ull;
312 static const uptr kLoAppMemBeg = 0x000000001000ull;
313 static const uptr kLoAppMemEnd = 0x010000000000ull;
314 static const uptr kHiAppMemBeg = 0x3e8000000000ull;
315 static const uptr kHiAppMemEnd = 0x400000000000ull; // 46 bits
316 static const uptr kAppMemMsk = 0x3c0000000000ull;
317 static const uptr kAppMemXor = 0x020000000000ull;
318 static const uptr kVdsoBeg = 0x7800000000000000ull;
319};
320
321/*
322C/C++ on linux/powerpc64 (47-bit VMA)
3230000 0000 1000 - 0100 0000 0000: main binary
3240100 0000 0000 - 0200 0000 0000: -
3250100 0000 0000 - 1000 0000 0000: shadow
3261000 0000 0000 - 1000 0000 0000: -
3271000 0000 0000 - 2000 0000 0000: metainfo (memory blocks and sync objects)
3282000 0000 0000 - 2000 0000 0000: -
3292000 0000 0000 - 2200 0000 0000: traces
3302200 0000 0000 - 7d00 0000 0000: -
3317d00 0000 0000 - 7e00 0000 0000: heap
3327e00 0000 0000 - 7e80 0000 0000: -
3337e80 0000 0000 - 8000 0000 0000: modules and main thread stack
334*/
335struct Mapping47 {
336 static const uptr kMetaShadowBeg = 0x100000000000ull;
337 static const uptr kMetaShadowEnd = 0x200000000000ull;
338 static const uptr kTraceMemBeg = 0x200000000000ull;
339 static const uptr kTraceMemEnd = 0x220000000000ull;
340 static const uptr kShadowBeg = 0x010000000000ull;
341 static const uptr kShadowEnd = 0x100000000000ull;
342 static const uptr kHeapMemBeg = 0x7d0000000000ull;
343 static const uptr kHeapMemEnd = 0x7e0000000000ull;
344 static const uptr kLoAppMemBeg = 0x000000001000ull;
345 static const uptr kLoAppMemEnd = 0x010000000000ull;
346 static const uptr kHiAppMemBeg = 0x7e8000000000ull;
347 static const uptr kHiAppMemEnd = 0x800000000000ull; // 47 bits
348 static const uptr kAppMemMsk = 0x7c0000000000ull;
349 static const uptr kAppMemXor = 0x020000000000ull;
350 static const uptr kVdsoBeg = 0x7800000000000000ull;
351};
352
353// Indicates the runtime will define the memory regions at runtime.
354#define TSAN_RUNTIME_VMA 1
355#endif
356
357#elif SANITIZER_GO && !SANITIZER_WINDOWS && defined(__x86_64__)
358
359/* Go on linux, darwin and freebsd on x86_64
3600000 0000 1000 - 0000 1000 0000: executable
3610000 1000 0000 - 00c0 0000 0000: -
36200c0 0000 0000 - 00e0 0000 0000: heap
36300e0 0000 0000 - 2000 0000 0000: -
3642000 0000 0000 - 2380 0000 0000: shadow
3652380 0000 0000 - 3000 0000 0000: -
3663000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects)
3674000 0000 0000 - 6000 0000 0000: -
3686000 0000 0000 - 6200 0000 0000: traces
3696200 0000 0000 - 8000 0000 0000: -
370*/
371
372struct Mapping {
373 static const uptr kMetaShadowBeg = 0x300000000000ull;
374 static const uptr kMetaShadowEnd = 0x400000000000ull;
375 static const uptr kTraceMemBeg = 0x600000000000ull;
376 static const uptr kTraceMemEnd = 0x620000000000ull;
377 static const uptr kShadowBeg = 0x200000000000ull;
378 static const uptr kShadowEnd = 0x238000000000ull;
379 static const uptr kAppMemBeg = 0x000000001000ull;
380 static const uptr kAppMemEnd = 0x00e000000000ull;
381};
382
383#elif SANITIZER_GO && SANITIZER_WINDOWS
384
385/* Go on windows
3860000 0000 1000 - 0000 1000 0000: executable
3870000 1000 0000 - 00f8 0000 0000: -
38800c0 0000 0000 - 00e0 0000 0000: heap
38900e0 0000 0000 - 0100 0000 0000: -
3900100 0000 0000 - 0500 0000 0000: shadow
3910500 0000 0000 - 0560 0000 0000: -
3920560 0000 0000 - 0760 0000 0000: traces
3930760 0000 0000 - 07d0 0000 0000: metainfo (memory blocks and sync objects)
39407d0 0000 0000 - 8000 0000 0000: -
395*/
396
397struct Mapping {
398 static const uptr kMetaShadowBeg = 0x076000000000ull;
399 static const uptr kMetaShadowEnd = 0x07d000000000ull;
400 static const uptr kTraceMemBeg = 0x056000000000ull;
401 static const uptr kTraceMemEnd = 0x076000000000ull;
402 static const uptr kShadowBeg = 0x010000000000ull;
403 static const uptr kShadowEnd = 0x050000000000ull;
404 static const uptr kAppMemBeg = 0x000000001000ull;
405 static const uptr kAppMemEnd = 0x00e000000000ull;
406};
407
408#elif SANITIZER_GO && defined(__powerpc64__)
409
410/* Only Mapping46 and Mapping47 are currently supported for powercp64 on Go. */
411
412/* Go on linux/powerpc64 (46-bit VMA)
4130000 0000 1000 - 0000 1000 0000: executable
4140000 1000 0000 - 00c0 0000 0000: -
41500c0 0000 0000 - 00e0 0000 0000: heap
41600e0 0000 0000 - 2000 0000 0000: -
4172000 0000 0000 - 2380 0000 0000: shadow
4182380 0000 0000 - 2400 0000 0000: -
4192400 0000 0000 - 3400 0000 0000: metainfo (memory blocks and sync objects)
4203400 0000 0000 - 3600 0000 0000: -
4213600 0000 0000 - 3800 0000 0000: traces
4223800 0000 0000 - 4000 0000 0000: -
423*/
424
425struct Mapping46 {
426 static const uptr kMetaShadowBeg = 0x240000000000ull;
427 static const uptr kMetaShadowEnd = 0x340000000000ull;
428 static const uptr kTraceMemBeg = 0x360000000000ull;
429 static const uptr kTraceMemEnd = 0x380000000000ull;
430 static const uptr kShadowBeg = 0x200000000000ull;
431 static const uptr kShadowEnd = 0x238000000000ull;
432 static const uptr kAppMemBeg = 0x000000001000ull;
433 static const uptr kAppMemEnd = 0x00e000000000ull;
434};
435
436/* Go on linux/powerpc64 (47-bit VMA)
4370000 0000 1000 - 0000 1000 0000: executable
4380000 1000 0000 - 00c0 0000 0000: -
43900c0 0000 0000 - 00e0 0000 0000: heap
44000e0 0000 0000 - 2000 0000 0000: -
4412000 0000 0000 - 3000 0000 0000: shadow
4423000 0000 0000 - 3000 0000 0000: -
4433000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects)
4444000 0000 0000 - 6000 0000 0000: -
4456000 0000 0000 - 6200 0000 0000: traces
4466200 0000 0000 - 8000 0000 0000: -
447*/
448
449struct Mapping47 {
450 static const uptr kMetaShadowBeg = 0x300000000000ull;
451 static const uptr kMetaShadowEnd = 0x400000000000ull;
452 static const uptr kTraceMemBeg = 0x600000000000ull;
453 static const uptr kTraceMemEnd = 0x620000000000ull;
454 static const uptr kShadowBeg = 0x200000000000ull;
455 static const uptr kShadowEnd = 0x300000000000ull;
456 static const uptr kAppMemBeg = 0x000000001000ull;
457 static const uptr kAppMemEnd = 0x00e000000000ull;
458};
459
460#define TSAN_RUNTIME_VMA 1
461
462#elif SANITIZER_GO && defined(__aarch64__)
463
464/* Go on linux/aarch64 (48-bit VMA)
4650000 0000 1000 - 0000 1000 0000: executable
4660000 1000 0000 - 00c0 0000 0000: -
46700c0 0000 0000 - 00e0 0000 0000: heap
46800e0 0000 0000 - 2000 0000 0000: -
4692000 0000 0000 - 3000 0000 0000: shadow
4703000 0000 0000 - 3000 0000 0000: -
4713000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects)
4724000 0000 0000 - 6000 0000 0000: -
4736000 0000 0000 - 6200 0000 0000: traces
4746200 0000 0000 - 8000 0000 0000: -
475*/
476
477struct Mapping {
478 static const uptr kMetaShadowBeg = 0x300000000000ull;
479 static const uptr kMetaShadowEnd = 0x400000000000ull;
480 static const uptr kTraceMemBeg = 0x600000000000ull;
481 static const uptr kTraceMemEnd = 0x620000000000ull;
482 static const uptr kShadowBeg = 0x200000000000ull;
483 static const uptr kShadowEnd = 0x300000000000ull;
484 static const uptr kAppMemBeg = 0x000000001000ull;
485 static const uptr kAppMemEnd = 0x00e000000000ull;
486};
487
488// Indicates the runtime will define the memory regions at runtime.
489#define TSAN_RUNTIME_VMA 1
490
491#else
492# error "Unknown platform"
493#endif
494
495
496#ifdef TSAN_RUNTIME_VMA
497extern uptr vmaSize;
498#endif
499
500
501enum MappingType {
502 MAPPING_LO_APP_BEG,
503 MAPPING_LO_APP_END,
504 MAPPING_HI_APP_BEG,
505 MAPPING_HI_APP_END,
506#ifdef TSAN_MID_APP_RANGE
507 MAPPING_MID_APP_BEG,
508 MAPPING_MID_APP_END,
509#endif
510 MAPPING_HEAP_BEG,
511 MAPPING_HEAP_END,
512 MAPPING_APP_BEG,
513 MAPPING_APP_END,
514 MAPPING_SHADOW_BEG,
515 MAPPING_SHADOW_END,
516 MAPPING_META_SHADOW_BEG,
517 MAPPING_META_SHADOW_END,
518 MAPPING_TRACE_BEG,
519 MAPPING_TRACE_END,
520 MAPPING_VDSO_BEG,
521};
522
523template<typename Mapping, int Type>
524uptr MappingImpl(void) {
525 switch (Type) {
526#if !SANITIZER_GO
527 case MAPPING_LO_APP_BEG: return Mapping::kLoAppMemBeg;
528 case MAPPING_LO_APP_END: return Mapping::kLoAppMemEnd;
529# ifdef TSAN_MID_APP_RANGE
530 case MAPPING_MID_APP_BEG: return Mapping::kMidAppMemBeg;
531 case MAPPING_MID_APP_END: return Mapping::kMidAppMemEnd;
532# endif
533 case MAPPING_HI_APP_BEG: return Mapping::kHiAppMemBeg;
534 case MAPPING_HI_APP_END: return Mapping::kHiAppMemEnd;
535 case MAPPING_HEAP_BEG: return Mapping::kHeapMemBeg;
536 case MAPPING_HEAP_END: return Mapping::kHeapMemEnd;
537 case MAPPING_VDSO_BEG: return Mapping::kVdsoBeg;
538#else
539 case MAPPING_APP_BEG: return Mapping::kAppMemBeg;
540 case MAPPING_APP_END: return Mapping::kAppMemEnd;
541#endif
542 case MAPPING_SHADOW_BEG: return Mapping::kShadowBeg;
543 case MAPPING_SHADOW_END: return Mapping::kShadowEnd;
544 case MAPPING_META_SHADOW_BEG: return Mapping::kMetaShadowBeg;
545 case MAPPING_META_SHADOW_END: return Mapping::kMetaShadowEnd;
546 case MAPPING_TRACE_BEG: return Mapping::kTraceMemBeg;
547 case MAPPING_TRACE_END: return Mapping::kTraceMemEnd;
548 }
549}
550
551template<int Type>
552uptr MappingArchImpl(void) {
553#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
554 switch (vmaSize) {
555 case 39: return MappingImpl<Mapping39, Type>();
556 case 42: return MappingImpl<Mapping42, Type>();
557 case 48: return MappingImpl<Mapping48, Type>();
558 }
559 DCHECK(0);
560 return 0;
561#elif defined(__powerpc64__)
562 switch (vmaSize) {
563#if !SANITIZER_GO
564 case 44: return MappingImpl<Mapping44, Type>();
565#endif
566 case 46: return MappingImpl<Mapping46, Type>();
567 case 47: return MappingImpl<Mapping47, Type>();
568 }
569 DCHECK(0);
570 return 0;
571#else
572 return MappingImpl<Mapping, Type>();
573#endif
574}
575
576#if !SANITIZER_GO
577ALWAYS_INLINE
578uptr LoAppMemBeg(void) {
579 return MappingArchImpl<MAPPING_LO_APP_BEG>();
580}
581ALWAYS_INLINE
582uptr LoAppMemEnd(void) {
583 return MappingArchImpl<MAPPING_LO_APP_END>();
584}
585
586#ifdef TSAN_MID_APP_RANGE
587ALWAYS_INLINE
588uptr MidAppMemBeg(void) {
589 return MappingArchImpl<MAPPING_MID_APP_BEG>();
590}
591ALWAYS_INLINE
592uptr MidAppMemEnd(void) {
593 return MappingArchImpl<MAPPING_MID_APP_END>();
594}
595#endif
596
597ALWAYS_INLINE
598uptr HeapMemBeg(void) {
599 return MappingArchImpl<MAPPING_HEAP_BEG>();
600}
601ALWAYS_INLINE
602uptr HeapMemEnd(void) {
603 return MappingArchImpl<MAPPING_HEAP_END>();
604}
605
606ALWAYS_INLINE
607uptr HiAppMemBeg(void) {
608 return MappingArchImpl<MAPPING_HI_APP_BEG>();
609}
610ALWAYS_INLINE
611uptr HiAppMemEnd(void) {
612 return MappingArchImpl<MAPPING_HI_APP_END>();
613}
614
615ALWAYS_INLINE
616uptr VdsoBeg(void) {
617 return MappingArchImpl<MAPPING_VDSO_BEG>();
618}
619
620#else
621
622ALWAYS_INLINE
623uptr AppMemBeg(void) {
624 return MappingArchImpl<MAPPING_APP_BEG>();
625}
626ALWAYS_INLINE
627uptr AppMemEnd(void) {
628 return MappingArchImpl<MAPPING_APP_END>();
629}
630
631#endif
632
633static inline
634bool GetUserRegion(int i, uptr *start, uptr *end) {
635 switch (i) {
636 default:
637 return false;
638#if !SANITIZER_GO
639 case 0:
640 *start = LoAppMemBeg();
641 *end = LoAppMemEnd();
642 return true;
643 case 1:
644 *start = HiAppMemBeg();
645 *end = HiAppMemEnd();
646 return true;
647 case 2:
648 *start = HeapMemBeg();
649 *end = HeapMemEnd();
650 return true;
651# ifdef TSAN_MID_APP_RANGE
652 case 3:
653 *start = MidAppMemBeg();
654 *end = MidAppMemEnd();
655 return true;
656# endif
657#else
658 case 0:
659 *start = AppMemBeg();
660 *end = AppMemEnd();
661 return true;
662#endif
663 }
664}
665
666ALWAYS_INLINE
667uptr ShadowBeg(void) {
668 return MappingArchImpl<MAPPING_SHADOW_BEG>();
669}
670ALWAYS_INLINE
671uptr ShadowEnd(void) {
672 return MappingArchImpl<MAPPING_SHADOW_END>();
673}
674
675ALWAYS_INLINE
676uptr MetaShadowBeg(void) {
677 return MappingArchImpl<MAPPING_META_SHADOW_BEG>();
678}
679ALWAYS_INLINE
680uptr MetaShadowEnd(void) {
681 return MappingArchImpl<MAPPING_META_SHADOW_END>();
682}
683
684ALWAYS_INLINE
685uptr TraceMemBeg(void) {
686 return MappingArchImpl<MAPPING_TRACE_BEG>();
687}
688ALWAYS_INLINE
689uptr TraceMemEnd(void) {
690 return MappingArchImpl<MAPPING_TRACE_END>();
691}
692
693
694template<typename Mapping>
695bool IsAppMemImpl(uptr mem) {
696#if !SANITIZER_GO
697 return (mem >= Mapping::kHeapMemBeg && mem < Mapping::kHeapMemEnd) ||
698# ifdef TSAN_MID_APP_RANGE
699 (mem >= Mapping::kMidAppMemBeg && mem < Mapping::kMidAppMemEnd) ||
700# endif
701 (mem >= Mapping::kLoAppMemBeg && mem < Mapping::kLoAppMemEnd) ||
702 (mem >= Mapping::kHiAppMemBeg && mem < Mapping::kHiAppMemEnd);
703#else
704 return mem >= Mapping::kAppMemBeg && mem < Mapping::kAppMemEnd;
705#endif
706}
707
708ALWAYS_INLINE
709bool IsAppMem(uptr mem) {
710#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
711 switch (vmaSize) {
712 case 39: return IsAppMemImpl<Mapping39>(mem);
713 case 42: return IsAppMemImpl<Mapping42>(mem);
714 case 48: return IsAppMemImpl<Mapping48>(mem);
715 }
716 DCHECK(0);
717 return false;
718#elif defined(__powerpc64__)
719 switch (vmaSize) {
720#if !SANITIZER_GO
721 case 44: return IsAppMemImpl<Mapping44>(mem);
722#endif
723 case 46: return IsAppMemImpl<Mapping46>(mem);
724 case 47: return IsAppMemImpl<Mapping47>(mem);
725 }
726 DCHECK(0);
727 return false;
728#else
729 return IsAppMemImpl<Mapping>(mem);
730#endif
731}
732
733
734template<typename Mapping>
735bool IsShadowMemImpl(uptr mem) {
736 return mem >= Mapping::kShadowBeg && mem <= Mapping::kShadowEnd;
737}
738
739ALWAYS_INLINE
740bool IsShadowMem(uptr mem) {
741#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
742 switch (vmaSize) {
743 case 39: return IsShadowMemImpl<Mapping39>(mem);
744 case 42: return IsShadowMemImpl<Mapping42>(mem);
745 case 48: return IsShadowMemImpl<Mapping48>(mem);
746 }
747 DCHECK(0);
748 return false;
749#elif defined(__powerpc64__)
750 switch (vmaSize) {
751#if !SANITIZER_GO
752 case 44: return IsShadowMemImpl<Mapping44>(mem);
753#endif
754 case 46: return IsShadowMemImpl<Mapping46>(mem);
755 case 47: return IsShadowMemImpl<Mapping47>(mem);
756 }
757 DCHECK(0);
758 return false;
759#else
760 return IsShadowMemImpl<Mapping>(mem);
761#endif
762}
763
764
765template<typename Mapping>
766bool IsMetaMemImpl(uptr mem) {
767 return mem >= Mapping::kMetaShadowBeg && mem <= Mapping::kMetaShadowEnd;
768}
769
770ALWAYS_INLINE
771bool IsMetaMem(uptr mem) {
772#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
773 switch (vmaSize) {
774 case 39: return IsMetaMemImpl<Mapping39>(mem);
775 case 42: return IsMetaMemImpl<Mapping42>(mem);
776 case 48: return IsMetaMemImpl<Mapping48>(mem);
777 }
778 DCHECK(0);
779 return false;
780#elif defined(__powerpc64__)
781 switch (vmaSize) {
782#if !SANITIZER_GO
783 case 44: return IsMetaMemImpl<Mapping44>(mem);
784#endif
785 case 46: return IsMetaMemImpl<Mapping46>(mem);
786 case 47: return IsMetaMemImpl<Mapping47>(mem);
787 }
788 DCHECK(0);
789 return false;
790#else
791 return IsMetaMemImpl<Mapping>(mem);
792#endif
793}
794
795
796template<typename Mapping>
797uptr MemToShadowImpl(uptr x) {
798 DCHECK(IsAppMem(x));
799#if !SANITIZER_GO
800 return (((x) & ~(Mapping::kAppMemMsk | (kShadowCell - 1)))
801 ^ Mapping::kAppMemXor) * kShadowCnt;
802#else
803# ifndef SANITIZER_WINDOWS
804 return ((x & ~(kShadowCell - 1)) * kShadowCnt) | Mapping::kShadowBeg;
805# else
806 return ((x & ~(kShadowCell - 1)) * kShadowCnt) + Mapping::kShadowBeg;
807# endif
808#endif
809}
810
811ALWAYS_INLINE
812uptr MemToShadow(uptr x) {
813#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
814 switch (vmaSize) {
815 case 39: return MemToShadowImpl<Mapping39>(x);
816 case 42: return MemToShadowImpl<Mapping42>(x);
817 case 48: return MemToShadowImpl<Mapping48>(x);
818 }
819 DCHECK(0);
820 return 0;
821#elif defined(__powerpc64__)
822 switch (vmaSize) {
823#if !SANITIZER_GO
824 case 44: return MemToShadowImpl<Mapping44>(x);
825#endif
826 case 46: return MemToShadowImpl<Mapping46>(x);
827 case 47: return MemToShadowImpl<Mapping47>(x);
828 }
829 DCHECK(0);
830 return 0;
831#else
832 return MemToShadowImpl<Mapping>(x);
833#endif
834}
835
836
837template<typename Mapping>
838u32 *MemToMetaImpl(uptr x) {
839 DCHECK(IsAppMem(x));
840#if !SANITIZER_GO
841 return (u32*)(((((x) & ~(Mapping::kAppMemMsk | (kMetaShadowCell - 1)))) /
842 kMetaShadowCell * kMetaShadowSize) | Mapping::kMetaShadowBeg);
843#else
844# ifndef SANITIZER_WINDOWS
845 return (u32*)(((x & ~(kMetaShadowCell - 1)) / \
846 kMetaShadowCell * kMetaShadowSize) | Mapping::kMetaShadowBeg);
847# else
848 return (u32*)(((x & ~(kMetaShadowCell - 1)) / \
849 kMetaShadowCell * kMetaShadowSize) + Mapping::kMetaShadowBeg);
850# endif
851#endif
852}
853
854ALWAYS_INLINE
855u32 *MemToMeta(uptr x) {
856#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
857 switch (vmaSize) {
858 case 39: return MemToMetaImpl<Mapping39>(x);
859 case 42: return MemToMetaImpl<Mapping42>(x);
860 case 48: return MemToMetaImpl<Mapping48>(x);
861 }
862 DCHECK(0);
863 return 0;
864#elif defined(__powerpc64__)
865 switch (vmaSize) {
866#if !SANITIZER_GO
867 case 44: return MemToMetaImpl<Mapping44>(x);
868#endif
869 case 46: return MemToMetaImpl<Mapping46>(x);
870 case 47: return MemToMetaImpl<Mapping47>(x);
871 }
872 DCHECK(0);
873 return 0;
874#else
875 return MemToMetaImpl<Mapping>(x);
876#endif
877}
878
879
880template<typename Mapping>
881uptr ShadowToMemImpl(uptr s) {
882 DCHECK(IsShadowMem(s));
883#if !SANITIZER_GO
884 // The shadow mapping is non-linear and we've lost some bits, so we don't have
885 // an easy way to restore the original app address. But the mapping is a
886 // bijection, so we try to restore the address as belonging to low/mid/high
887 // range consecutively and see if shadow->app->shadow mapping gives us the
888 // same address.
889 uptr p = (s / kShadowCnt) ^ Mapping::kAppMemXor;
890 if (p >= Mapping::kLoAppMemBeg && p < Mapping::kLoAppMemEnd &&
891 MemToShadow(p) == s)
892 return p;
893# ifdef TSAN_MID_APP_RANGE
894 p = ((s / kShadowCnt) ^ Mapping::kAppMemXor) +
895 (Mapping::kMidAppMemBeg & Mapping::kAppMemMsk);
896 if (p >= Mapping::kMidAppMemBeg && p < Mapping::kMidAppMemEnd &&
897 MemToShadow(p) == s)
898 return p;
899# endif
900 return ((s / kShadowCnt) ^ Mapping::kAppMemXor) | Mapping::kAppMemMsk;
901#else // #if !SANITIZER_GO
902# ifndef SANITIZER_WINDOWS
903 return (s & ~Mapping::kShadowBeg) / kShadowCnt;
904# else
905 return (s - Mapping::kShadowBeg) / kShadowCnt;
906# endif // SANITIZER_WINDOWS
907#endif
908}
909
910ALWAYS_INLINE
911uptr ShadowToMem(uptr s) {
912#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
913 switch (vmaSize) {
914 case 39: return ShadowToMemImpl<Mapping39>(s);
915 case 42: return ShadowToMemImpl<Mapping42>(s);
916 case 48: return ShadowToMemImpl<Mapping48>(s);
917 }
918 DCHECK(0);
919 return 0;
920#elif defined(__powerpc64__)
921 switch (vmaSize) {
922#if !SANITIZER_GO
923 case 44: return ShadowToMemImpl<Mapping44>(s);
924#endif
925 case 46: return ShadowToMemImpl<Mapping46>(s);
926 case 47: return ShadowToMemImpl<Mapping47>(s);
927 }
928 DCHECK(0);
929 return 0;
930#else
931 return ShadowToMemImpl<Mapping>(s);
932#endif
933}
934
935
936
937// The additional page is to catch shadow stack overflow as paging fault.
938// Windows wants 64K alignment for mmaps.
939const uptr kTotalTraceSize = (kTraceSize * sizeof(Event) + sizeof(Trace)
940 + (64 << 10) + (64 << 10) - 1) & ~((64 << 10) - 1);
941
942template<typename Mapping>
943uptr GetThreadTraceImpl(int tid) {
944 uptr p = Mapping::kTraceMemBeg + (uptr)tid * kTotalTraceSize;
945 DCHECK_LT(p, Mapping::kTraceMemEnd);
946 return p;
947}
948
949ALWAYS_INLINE
950uptr GetThreadTrace(int tid) {
951#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
952 switch (vmaSize) {
953 case 39: return GetThreadTraceImpl<Mapping39>(tid);
954 case 42: return GetThreadTraceImpl<Mapping42>(tid);
955 case 48: return GetThreadTraceImpl<Mapping48>(tid);
956 }
957 DCHECK(0);
958 return 0;
959#elif defined(__powerpc64__)
960 switch (vmaSize) {
961#if !SANITIZER_GO
962 case 44: return GetThreadTraceImpl<Mapping44>(tid);
963#endif
964 case 46: return GetThreadTraceImpl<Mapping46>(tid);
965 case 47: return GetThreadTraceImpl<Mapping47>(tid);
966 }
967 DCHECK(0);
968 return 0;
969#else
970 return GetThreadTraceImpl<Mapping>(tid);
971#endif
972}
973
974
975template<typename Mapping>
976uptr GetThreadTraceHeaderImpl(int tid) {
977 uptr p = Mapping::kTraceMemBeg + (uptr)tid * kTotalTraceSize
978 + kTraceSize * sizeof(Event);
979 DCHECK_LT(p, Mapping::kTraceMemEnd);
980 return p;
981}
982
983ALWAYS_INLINE
984uptr GetThreadTraceHeader(int tid) {
985#if defined(__aarch64__) && !defined(__APPLE__) && !SANITIZER_GO
986 switch (vmaSize) {
987 case 39: return GetThreadTraceHeaderImpl<Mapping39>(tid);
988 case 42: return GetThreadTraceHeaderImpl<Mapping42>(tid);
989 case 48: return GetThreadTraceHeaderImpl<Mapping48>(tid);
990 }
991 DCHECK(0);
992 return 0;
993#elif defined(__powerpc64__)
994 switch (vmaSize) {
995#if !SANITIZER_GO
996 case 44: return GetThreadTraceHeaderImpl<Mapping44>(tid);
997#endif
998 case 46: return GetThreadTraceHeaderImpl<Mapping46>(tid);
999 case 47: return GetThreadTraceHeaderImpl<Mapping47>(tid);
1000 }
1001 DCHECK(0);
1002 return 0;
1003#else
1004 return GetThreadTraceHeaderImpl<Mapping>(tid);
1005#endif
1006}
1007
1008void InitializePlatform();
1009void InitializePlatformEarly();
1010void CheckAndProtect();
1011void InitializeShadowMemoryPlatform();
1012void FlushShadowMemory();
1013void WriteMemoryProfile(char *buf, uptr buf_size, uptr nthread, uptr nlive);
1014int ExtractResolvFDs(void *state, int *fds, int nfd);
1015int ExtractRecvmsgFDs(void *msg, int *fds, int nfd);
1016uptr ExtractLongJmpSp(uptr *env);
1017void ImitateTlsWrite(ThreadState *thr, uptr tls_addr, uptr tls_size);
1018
1019int call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m,
1020 void *abstime), void *c, void *m, void *abstime,
1021 void(*cleanup)(void *arg), void *arg);
1022
1023void DestroyThreadState();
1024void PlatformCleanUpThreadState(ThreadState *thr);
1025
1026} // namespace __tsan
1027
1028#endif // TSAN_PLATFORM_H
lib/tsan/tsan_ppc_regs.h created+96
...@@ -0,0 +1,96 @@
1#define r0 0
2#define r1 1
3#define r2 2
4#define r3 3
5#define r4 4
6#define r5 5
7#define r6 6
8#define r7 7
9#define r8 8
10#define r9 9
11#define r10 10
12#define r11 11
13#define r12 12
14#define r13 13
15#define r14 14
16#define r15 15
17#define r16 16
18#define r17 17
19#define r18 18
20#define r19 19
21#define r20 20
22#define r21 21
23#define r22 22
24#define r23 23
25#define r24 24
26#define r25 25
27#define r26 26
28#define r27 27
29#define r28 28
30#define r29 29
31#define r30 30
32#define r31 31
33#define f0 0
34#define f1 1
35#define f2 2
36#define f3 3
37#define f4 4
38#define f5 5
39#define f6 6
40#define f7 7
41#define f8 8
42#define f9 9
43#define f10 10
44#define f11 11
45#define f12 12
46#define f13 13
47#define f14 14
48#define f15 15
49#define f16 16
50#define f17 17
51#define f18 18
52#define f19 19
53#define f20 20
54#define f21 21
55#define f22 22
56#define f23 23
57#define f24 24
58#define f25 25
59#define f26 26
60#define f27 27
61#define f28 28
62#define f29 29
63#define f30 30
64#define f31 31
65#define v0 0
66#define v1 1
67#define v2 2
68#define v3 3
69#define v4 4
70#define v5 5
71#define v6 6
72#define v7 7
73#define v8 8
74#define v9 9
75#define v10 10
76#define v11 11
77#define v12 12
78#define v13 13
79#define v14 14
80#define v15 15
81#define v16 16
82#define v17 17
83#define v18 18
84#define v19 19
85#define v20 20
86#define v21 21
87#define v22 22
88#define v23 23
89#define v24 24
90#define v25 25
91#define v26 26
92#define v27 27
93#define v28 28
94#define v29 29
95#define v30 30
96#define v31 31
lib/tsan/tsan_preinit.cpp created+26
...@@ -0,0 +1,26 @@
1//===-- tsan_preinit.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.
10//
11// Call __tsan_init at the very early stage of process startup.
12//===----------------------------------------------------------------------===//
13
14#include "sanitizer_common/sanitizer_internal_defs.h"
15#include "tsan_interface.h"
16
17#if SANITIZER_CAN_USE_PREINIT_ARRAY
18
19// The symbol is called __local_tsan_preinit, because it's not intended to be
20// exported.
21// This code linked into the main executable when -fsanitize=thread is in
22// the link flags. It can only use exported interface functions.
23__attribute__((section(".preinit_array"), used))
24void (*__local_tsan_preinit)(void) = __tsan_init;
25
26#endif
lib/tsan/tsan_report.cpp created+486
...@@ -0,0 +1,486 @@
1//===-- tsan_report.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_report.h"
13#include "tsan_platform.h"
14#include "tsan_rtl.h"
15#include "sanitizer_common/sanitizer_file.h"
16#include "sanitizer_common/sanitizer_placement_new.h"
17#include "sanitizer_common/sanitizer_report_decorator.h"
18#include "sanitizer_common/sanitizer_stacktrace_printer.h"
19
20namespace __tsan {
21
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
38class Decorator: public __sanitizer::SanitizerCommonDecorator {
39 public:
40 Decorator() : SanitizerCommonDecorator() { }
41 const char *Access() { return Blue(); }
42 const char *ThreadDescription() { return Cyan(); }
43 const char *Location() { return Green(); }
44 const char *Sleep() { return Yellow(); }
45 const char *Mutex() { return Magenta(); }
46};
47
48ReportDesc::ReportDesc()
49 : tag(kExternalTagNone)
50 , stacks()
51 , mops()
52 , locs()
53 , mutexes()
54 , threads()
55 , unique_tids()
56 , sleep()
57 , count() {
58}
59
60ReportMop::ReportMop()
61 : mset() {
62}
63
64ReportDesc::~ReportDesc() {
65 // FIXME(dvyukov): it must be leaking a lot of memory.
66}
67
68#if !SANITIZER_GO
69
70const int kThreadBufSize = 32;
71const char *thread_name(char *buf, int tid) {
72 if (tid == 0)
73 return "main thread";
74 internal_snprintf(buf, kThreadBufSize, "thread T%d", tid);
75 return buf;
76}
77
78static const char *ReportTypeString(ReportType typ, uptr tag) {
79 switch (typ) {
80 case ReportTypeRace:
81 return "data race";
82 case ReportTypeVptrRace:
83 return "data race on vptr (ctor/dtor vs virtual call)";
84 case ReportTypeUseAfterFree:
85 return "heap-use-after-free";
86 case ReportTypeVptrUseAfterFree:
87 return "heap-use-after-free (virtual call vs free)";
88 case ReportTypeExternalRace: {
89 const char *str = GetReportHeaderFromTag(tag);
90 return str ? str : "race on external object";
91 }
92 case ReportTypeThreadLeak:
93 return "thread leak";
94 case ReportTypeMutexDestroyLocked:
95 return "destroy of a locked mutex";
96 case ReportTypeMutexDoubleLock:
97 return "double lock of a mutex";
98 case ReportTypeMutexInvalidAccess:
99 return "use of an invalid mutex (e.g. uninitialized or destroyed)";
100 case ReportTypeMutexBadUnlock:
101 return "unlock of an unlocked mutex (or by a wrong thread)";
102 case ReportTypeMutexBadReadLock:
103 return "read lock of a write locked mutex";
104 case ReportTypeMutexBadReadUnlock:
105 return "read unlock of a write locked mutex";
106 case ReportTypeSignalUnsafe:
107 return "signal-unsafe call inside of a signal";
108 case ReportTypeErrnoInSignal:
109 return "signal handler spoils errno";
110 case ReportTypeDeadlock:
111 return "lock-order-inversion (potential deadlock)";
112 // No default case so compiler warns us if we miss one
113 }
114 UNREACHABLE("missing case");
115}
116
117#if SANITIZER_MAC
118static const char *const kInterposedFunctionPrefix = "wrap_";
119#else
120static const char *const kInterposedFunctionPrefix = "__interceptor_";
121#endif
122
123void PrintStack(const ReportStack *ent) {
124 if (ent == 0 || ent->frames == 0) {
125 Printf(" [failed to restore the stack]\n\n");
126 return;
127 }
128 SymbolizedStack *frame = ent->frames;
129 for (int i = 0; frame && frame->info.address; frame = frame->next, i++) {
130 InternalScopedString res(2 * GetPageSizeCached());
131 RenderFrame(&res, common_flags()->stack_trace_format, i, frame->info,
132 common_flags()->symbolize_vs_style,
133 common_flags()->strip_path_prefix, kInterposedFunctionPrefix);
134 Printf("%s\n", res.data());
135 }
136 Printf("\n");
137}
138
139static void PrintMutexSet(Vector<ReportMopMutex> const& mset) {
140 for (uptr i = 0; i < mset.Size(); i++) {
141 if (i == 0)
142 Printf(" (mutexes:");
143 const ReportMopMutex m = mset[i];
144 Printf(" %s M%llu", m.write ? "write" : "read", m.id);
145 Printf(i == mset.Size() - 1 ? ")" : ",");
146 }
147}
148
149static const char *MopDesc(bool first, bool write, bool atomic) {
150 return atomic ? (first ? (write ? "Atomic write" : "Atomic read")
151 : (write ? "Previous atomic write" : "Previous atomic read"))
152 : (first ? (write ? "Write" : "Read")
153 : (write ? "Previous write" : "Previous read"));
154}
155
156static const char *ExternalMopDesc(bool first, bool write) {
157 return first ? (write ? "Modifying" : "Read-only")
158 : (write ? "Previous modifying" : "Previous read-only");
159}
160
161static void PrintMop(const ReportMop *mop, bool first) {
162 Decorator d;
163 char thrbuf[kThreadBufSize];
164 Printf("%s", d.Access());
165 if (mop->external_tag == kExternalTagNone) {
166 Printf(" %s of size %d at %p by %s",
167 MopDesc(first, mop->write, mop->atomic), mop->size,
168 (void *)mop->addr, thread_name(thrbuf, mop->tid));
169 } else {
170 const char *object_type = GetObjectTypeFromTag(mop->external_tag);
171 if (object_type == nullptr)
172 object_type = "external object";
173 Printf(" %s access of %s at %p by %s",
174 ExternalMopDesc(first, mop->write), object_type,
175 (void *)mop->addr, thread_name(thrbuf, mop->tid));
176 }
177 PrintMutexSet(mop->mset);
178 Printf(":\n");
179 Printf("%s", d.Default());
180 PrintStack(mop->stack);
181}
182
183static void PrintLocation(const ReportLocation *loc) {
184 Decorator d;
185 char thrbuf[kThreadBufSize];
186 bool print_stack = false;
187 Printf("%s", d.Location());
188 if (loc->type == ReportLocationGlobal) {
189 const DataInfo &global = loc->global;
190 if (global.size != 0)
191 Printf(" Location is global '%s' of size %zu at %p (%s+%p)\n\n",
192 global.name, global.size, global.start,
193 StripModuleName(global.module), global.module_offset);
194 else
195 Printf(" Location is global '%s' at %p (%s+%p)\n\n", global.name,
196 global.start, StripModuleName(global.module),
197 global.module_offset);
198 } else if (loc->type == ReportLocationHeap) {
199 char thrbuf[kThreadBufSize];
200 const char *object_type = GetObjectTypeFromTag(loc->external_tag);
201 if (!object_type) {
202 Printf(" Location is heap block of size %zu at %p allocated by %s:\n",
203 loc->heap_chunk_size, loc->heap_chunk_start,
204 thread_name(thrbuf, loc->tid));
205 } else {
206 Printf(" Location is %s of size %zu at %p allocated by %s:\n",
207 object_type, loc->heap_chunk_size, loc->heap_chunk_start,
208 thread_name(thrbuf, loc->tid));
209 }
210 print_stack = true;
211 } else if (loc->type == ReportLocationStack) {
212 Printf(" Location is stack of %s.\n\n", thread_name(thrbuf, loc->tid));
213 } else if (loc->type == ReportLocationTLS) {
214 Printf(" Location is TLS of %s.\n\n", thread_name(thrbuf, loc->tid));
215 } else if (loc->type == ReportLocationFD) {
216 Printf(" Location is file descriptor %d created by %s at:\n",
217 loc->fd, thread_name(thrbuf, loc->tid));
218 print_stack = true;
219 }
220 Printf("%s", d.Default());
221 if (print_stack)
222 PrintStack(loc->stack);
223}
224
225static void PrintMutexShort(const ReportMutex *rm, const char *after) {
226 Decorator d;
227 Printf("%sM%zd%s%s", d.Mutex(), rm->id, d.Default(), after);
228}
229
230static void PrintMutexShortWithAddress(const ReportMutex *rm,
231 const char *after) {
232 Decorator d;
233 Printf("%sM%zd (%p)%s%s", d.Mutex(), rm->id, rm->addr, d.Default(), after);
234}
235
236static void PrintMutex(const ReportMutex *rm) {
237 Decorator d;
238 if (rm->destroyed) {
239 Printf("%s", d.Mutex());
240 Printf(" Mutex M%llu is already destroyed.\n\n", rm->id);
241 Printf("%s", d.Default());
242 } else {
243 Printf("%s", d.Mutex());
244 Printf(" Mutex M%llu (%p) created at:\n", rm->id, rm->addr);
245 Printf("%s", d.Default());
246 PrintStack(rm->stack);
247 }
248}
249
250static void PrintThread(const ReportThread *rt) {
251 Decorator d;
252 if (rt->id == 0) // Little sense in describing the main thread.
253 return;
254 Printf("%s", d.ThreadDescription());
255 Printf(" Thread T%d", rt->id);
256 if (rt->name && rt->name[0] != '\0')
257 Printf(" '%s'", rt->name);
258 char thrbuf[kThreadBufSize];
259 const char *thread_status = rt->running ? "running" : "finished";
260 if (rt->thread_type == ThreadType::Worker) {
261 Printf(" (tid=%zu, %s) is a GCD worker thread\n", rt->os_id, thread_status);
262 Printf("\n");
263 Printf("%s", d.Default());
264 return;
265 }
266 Printf(" (tid=%zu, %s) created by %s", rt->os_id, thread_status,
267 thread_name(thrbuf, rt->parent_tid));
268 if (rt->stack)
269 Printf(" at:");
270 Printf("\n");
271 Printf("%s", d.Default());
272 PrintStack(rt->stack);
273}
274
275static void PrintSleep(const ReportStack *s) {
276 Decorator d;
277 Printf("%s", d.Sleep());
278 Printf(" As if synchronized via sleep:\n");
279 Printf("%s", d.Default());
280 PrintStack(s);
281}
282
283static ReportStack *ChooseSummaryStack(const ReportDesc *rep) {
284 if (rep->mops.Size())
285 return rep->mops[0]->stack;
286 if (rep->stacks.Size())
287 return rep->stacks[0];
288 if (rep->mutexes.Size())
289 return rep->mutexes[0]->stack;
290 if (rep->threads.Size())
291 return rep->threads[0]->stack;
292 return 0;
293}
294
295static bool FrameIsInternal(const SymbolizedStack *frame) {
296 if (frame == 0)
297 return false;
298 const char *file = frame->info.file;
299 const char *module = frame->info.module;
300 if (file != 0 &&
301 (internal_strstr(file, "tsan_interceptors_posix.cpp") ||
302 internal_strstr(file, "sanitizer_common_interceptors.inc") ||
303 internal_strstr(file, "tsan_interface_")))
304 return true;
305 if (module != 0 && (internal_strstr(module, "libclang_rt.tsan_")))
306 return true;
307 return false;
308}
309
310static SymbolizedStack *SkipTsanInternalFrames(SymbolizedStack *frames) {
311 while (FrameIsInternal(frames) && frames->next)
312 frames = frames->next;
313 return frames;
314}
315
316void PrintReport(const ReportDesc *rep) {
317 Decorator d;
318 Printf("==================\n");
319 const char *rep_typ_str = ReportTypeString(rep->typ, rep->tag);
320 Printf("%s", d.Warning());
321 Printf("WARNING: ThreadSanitizer: %s (pid=%d)\n", rep_typ_str,
322 (int)internal_getpid());
323 Printf("%s", d.Default());
324
325 if (rep->typ == ReportTypeDeadlock) {
326 char thrbuf[kThreadBufSize];
327 Printf(" Cycle in lock order graph: ");
328 for (uptr i = 0; i < rep->mutexes.Size(); i++)
329 PrintMutexShortWithAddress(rep->mutexes[i], " => ");
330 PrintMutexShort(rep->mutexes[0], "\n\n");
331 CHECK_GT(rep->mutexes.Size(), 0U);
332 CHECK_EQ(rep->mutexes.Size() * (flags()->second_deadlock_stack ? 2 : 1),
333 rep->stacks.Size());
334 for (uptr i = 0; i < rep->mutexes.Size(); i++) {
335 Printf(" Mutex ");
336 PrintMutexShort(rep->mutexes[(i + 1) % rep->mutexes.Size()],
337 " acquired here while holding mutex ");
338 PrintMutexShort(rep->mutexes[i], " in ");
339 Printf("%s", d.ThreadDescription());
340 Printf("%s:\n", thread_name(thrbuf, rep->unique_tids[i]));
341 Printf("%s", d.Default());
342 if (flags()->second_deadlock_stack) {
343 PrintStack(rep->stacks[2*i]);
344 Printf(" Mutex ");
345 PrintMutexShort(rep->mutexes[i],
346 " previously acquired by the same thread here:\n");
347 PrintStack(rep->stacks[2*i+1]);
348 } else {
349 PrintStack(rep->stacks[i]);
350 if (i == 0)
351 Printf(" Hint: use TSAN_OPTIONS=second_deadlock_stack=1 "
352 "to get more informative warning message\n\n");
353 }
354 }
355 } else {
356 for (uptr i = 0; i < rep->stacks.Size(); i++) {
357 if (i)
358 Printf(" and:\n");
359 PrintStack(rep->stacks[i]);
360 }
361 }
362
363 for (uptr i = 0; i < rep->mops.Size(); i++)
364 PrintMop(rep->mops[i], i == 0);
365
366 if (rep->sleep)
367 PrintSleep(rep->sleep);
368
369 for (uptr i = 0; i < rep->locs.Size(); i++)
370 PrintLocation(rep->locs[i]);
371
372 if (rep->typ != ReportTypeDeadlock) {
373 for (uptr i = 0; i < rep->mutexes.Size(); i++)
374 PrintMutex(rep->mutexes[i]);
375 }
376
377 for (uptr i = 0; i < rep->threads.Size(); i++)
378 PrintThread(rep->threads[i]);
379
380 if (rep->typ == ReportTypeThreadLeak && rep->count > 1)
381 Printf(" And %d more similar thread leaks.\n\n", rep->count - 1);
382
383 if (ReportStack *stack = ChooseSummaryStack(rep)) {
384 if (SymbolizedStack *frame = SkipTsanInternalFrames(stack->frames))
385 ReportErrorSummary(rep_typ_str, frame->info);
386 }
387
388 if (common_flags()->print_module_map == 2) PrintModuleMap();
389
390 Printf("==================\n");
391}
392
393#else // #if !SANITIZER_GO
394
395const int kMainThreadId = 1;
396
397void PrintStack(const ReportStack *ent) {
398 if (ent == 0 || ent->frames == 0) {
399 Printf(" [failed to restore the stack]\n");
400 return;
401 }
402 SymbolizedStack *frame = ent->frames;
403 for (int i = 0; frame; frame = frame->next, i++) {
404 const AddressInfo &info = frame->info;
405 Printf(" %s()\n %s:%d +0x%zx\n", info.function,
406 StripPathPrefix(info.file, common_flags()->strip_path_prefix),
407 info.line, (void *)info.module_offset);
408 }
409}
410
411static void PrintMop(const ReportMop *mop, bool first) {
412 Printf("\n");
413 Printf("%s at %p by ",
414 (first ? (mop->write ? "Write" : "Read")
415 : (mop->write ? "Previous write" : "Previous read")), mop->addr);
416 if (mop->tid == kMainThreadId)
417 Printf("main goroutine:\n");
418 else
419 Printf("goroutine %d:\n", mop->tid);
420 PrintStack(mop->stack);
421}
422
423static void PrintLocation(const ReportLocation *loc) {
424 switch (loc->type) {
425 case ReportLocationHeap: {
426 Printf("\n");
427 Printf("Heap block of size %zu at %p allocated by ",
428 loc->heap_chunk_size, loc->heap_chunk_start);
429 if (loc->tid == kMainThreadId)
430 Printf("main goroutine:\n");
431 else
432 Printf("goroutine %d:\n", loc->tid);
433 PrintStack(loc->stack);
434 break;
435 }
436 case ReportLocationGlobal: {
437 Printf("\n");
438 Printf("Global var %s of size %zu at %p declared at %s:%zu\n",
439 loc->global.name, loc->global.size, loc->global.start,
440 loc->global.file, loc->global.line);
441 break;
442 }
443 default:
444 break;
445 }
446}
447
448static void PrintThread(const ReportThread *rt) {
449 if (rt->id == kMainThreadId)
450 return;
451 Printf("\n");
452 Printf("Goroutine %d (%s) created at:\n",
453 rt->id, rt->running ? "running" : "finished");
454 PrintStack(rt->stack);
455}
456
457void PrintReport(const ReportDesc *rep) {
458 Printf("==================\n");
459 if (rep->typ == ReportTypeRace) {
460 Printf("WARNING: DATA RACE");
461 for (uptr i = 0; i < rep->mops.Size(); i++)
462 PrintMop(rep->mops[i], i == 0);
463 for (uptr i = 0; i < rep->locs.Size(); i++)
464 PrintLocation(rep->locs[i]);
465 for (uptr i = 0; i < rep->threads.Size(); i++)
466 PrintThread(rep->threads[i]);
467 } else if (rep->typ == ReportTypeDeadlock) {
468 Printf("WARNING: DEADLOCK\n");
469 for (uptr i = 0; i < rep->mutexes.Size(); i++) {
470 Printf("Goroutine %d lock mutex %d while holding mutex %d:\n",
471 999, rep->mutexes[i]->id,
472 rep->mutexes[(i+1) % rep->mutexes.Size()]->id);
473 PrintStack(rep->stacks[2*i]);
474 Printf("\n");
475 Printf("Mutex %d was previously locked here:\n",
476 rep->mutexes[(i+1) % rep->mutexes.Size()]->id);
477 PrintStack(rep->stacks[2*i + 1]);
478 Printf("\n");
479 }
480 }
481 Printf("==================\n");
482}
483
484#endif
485
486} // namespace __tsan
lib/tsan/tsan_report.h created+135
...@@ -0,0 +1,135 @@
1//===-- tsan_report.h -------------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file is a part of ThreadSanitizer (TSan), a race detector.
10//
11//===----------------------------------------------------------------------===//
12#ifndef TSAN_REPORT_H
13#define TSAN_REPORT_H
14
15#include "sanitizer_common/sanitizer_symbolizer.h"
16#include "sanitizer_common/sanitizer_thread_registry.h"
17#include "sanitizer_common/sanitizer_vector.h"
18#include "tsan_defs.h"
19
20namespace __tsan {
21
22enum ReportType {
23 ReportTypeRace,
24 ReportTypeVptrRace,
25 ReportTypeUseAfterFree,
26 ReportTypeVptrUseAfterFree,
27 ReportTypeExternalRace,
28 ReportTypeThreadLeak,
29 ReportTypeMutexDestroyLocked,
30 ReportTypeMutexDoubleLock,
31 ReportTypeMutexInvalidAccess,
32 ReportTypeMutexBadUnlock,
33 ReportTypeMutexBadReadLock,
34 ReportTypeMutexBadReadUnlock,
35 ReportTypeSignalUnsafe,
36 ReportTypeErrnoInSignal,
37 ReportTypeDeadlock
38};
39
40struct ReportStack {
41 SymbolizedStack *frames;
42 bool suppressable;
43 static ReportStack *New();
44
45 private:
46 ReportStack();
47};
48
49struct ReportMopMutex {
50 u64 id;
51 bool write;
52};
53
54struct ReportMop {
55 int tid;
56 uptr addr;
57 int size;
58 bool write;
59 bool atomic;
60 uptr external_tag;
61 Vector<ReportMopMutex> mset;
62 ReportStack *stack;
63
64 ReportMop();
65};
66
67enum ReportLocationType {
68 ReportLocationGlobal,
69 ReportLocationHeap,
70 ReportLocationStack,
71 ReportLocationTLS,
72 ReportLocationFD
73};
74
75struct 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);
89};
90
91struct ReportThread {
92 int id;
93 tid_t os_id;
94 bool running;
95 ThreadType thread_type;
96 char *name;
97 u32 parent_tid;
98 ReportStack *stack;
99};
100
101struct ReportMutex {
102 u64 id;
103 uptr addr;
104 bool destroyed;
105 ReportStack *stack;
106};
107
108class ReportDesc {
109 public:
110 ReportType typ;
111 uptr tag;
112 Vector<ReportStack*> stacks;
113 Vector<ReportMop*> mops;
114 Vector<ReportLocation*> locs;
115 Vector<ReportMutex*> mutexes;
116 Vector<ReportThread*> threads;
117 Vector<int> unique_tids;
118 ReportStack *sleep;
119 int count;
120
121 ReportDesc();
122 ~ReportDesc();
123
124 private:
125 ReportDesc(const ReportDesc&);
126 void operator = (const ReportDesc&);
127};
128
129// Format and output the report to the console/log. No additional logic.
130void PrintReport(const ReportDesc *rep);
131void PrintStack(const ReportStack *stack);
132
133} // namespace __tsan
134
135#endif // TSAN_REPORT_H
lib/tsan/tsan_rtl.cpp created+1127
...@@ -0,0 +1,1127 @@
1//===-- tsan_rtl.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// Main file (entry points) for the TSan run-time.
12//===----------------------------------------------------------------------===//
13
14#include "sanitizer_common/sanitizer_atomic.h"
15#include "sanitizer_common/sanitizer_common.h"
16#include "sanitizer_common/sanitizer_file.h"
17#include "sanitizer_common/sanitizer_libc.h"
18#include "sanitizer_common/sanitizer_stackdepot.h"
19#include "sanitizer_common/sanitizer_placement_new.h"
20#include "sanitizer_common/sanitizer_symbolizer.h"
21#include "tsan_defs.h"
22#include "tsan_platform.h"
23#include "tsan_rtl.h"
24#include "tsan_mman.h"
25#include "tsan_suppressions.h"
26#include "tsan_symbolize.h"
27#include "ubsan/ubsan_init.h"
28
29#ifdef __SSE3__
30// <emmintrin.h> transitively includes <stdlib.h>,
31// and it's prohibited to include std headers into tsan runtime.
32// So we do this dirty trick.
33#define _MM_MALLOC_H_INCLUDED
34#define __MM_MALLOC_H
35#include <emmintrin.h>
36typedef __m128i m128;
37#endif
38
39volatile int __tsan_resumed = 0;
40
41extern "C" void __tsan_resume() {
42 __tsan_resumed = 1;
43}
44
45namespace __tsan {
46
47#if !SANITIZER_GO && !SANITIZER_MAC
48__attribute__((tls_model("initial-exec")))
49THREADLOCAL char cur_thread_placeholder[sizeof(ThreadState)] ALIGNED(64);
50#endif
51static char ctx_placeholder[sizeof(Context)] ALIGNED(64);
52Context *ctx;
53
54// Can be overriden by a front-end.
55#ifdef TSAN_EXTERNAL_HOOKS
56bool OnFinalize(bool failed);
57void OnInitialize();
58#else
59SANITIZER_WEAK_CXX_DEFAULT_IMPL
60bool OnFinalize(bool failed) {
61 return failed;
62}
63SANITIZER_WEAK_CXX_DEFAULT_IMPL
64void OnInitialize() {}
65#endif
66
67static char thread_registry_placeholder[sizeof(ThreadRegistry)];
68
69static ThreadContextBase *CreateThreadContext(u32 tid) {
70 // Map thread trace when context is created.
71 char name[50];
72 internal_snprintf(name, sizeof(name), "trace %u", tid);
73 MapThreadTrace(GetThreadTrace(tid), TraceSize() * sizeof(Event), name);
74 const uptr hdr = GetThreadTraceHeader(tid);
75 internal_snprintf(name, sizeof(name), "trace header %u", tid);
76 MapThreadTrace(hdr, sizeof(Trace), name);
77 new((void*)hdr) Trace();
78 // We are going to use only a small part of the trace with the default
79 // value of history_size. However, the constructor writes to the whole trace.
80 // Unmap the unused part.
81 uptr hdr_end = hdr + sizeof(Trace);
82 hdr_end -= sizeof(TraceHeader) * (kTraceParts - TraceParts());
83 hdr_end = RoundUp(hdr_end, GetPageSizeCached());
84 if (hdr_end < hdr + sizeof(Trace))
85 UnmapOrDie((void*)hdr_end, hdr + sizeof(Trace) - hdr_end);
86 void *mem = internal_alloc(MBlockThreadContex, sizeof(ThreadContext));
87 return new(mem) ThreadContext(tid);
88}
89
90#if !SANITIZER_GO
91static const u32 kThreadQuarantineSize = 16;
92#else
93static const u32 kThreadQuarantineSize = 64;
94#endif
95
96Context::Context()
97 : initialized()
98 , report_mtx(MutexTypeReport, StatMtxReport)
99 , nreported()
100 , nmissed_expected()
101 , thread_registry(new(thread_registry_placeholder) ThreadRegistry(
102 CreateThreadContext, kMaxTid, kThreadQuarantineSize, kMaxTidReuse))
103 , racy_mtx(MutexTypeRacy, StatMtxRacy)
104 , racy_stacks()
105 , racy_addresses()
106 , fired_suppressions_mtx(MutexTypeFired, StatMtxFired)
107 , clock_alloc("clock allocator") {
108 fired_suppressions.reserve(8);
109}
110
111// The objects are allocated in TLS, so one may rely on zero-initialization.
112ThreadState::ThreadState(Context *ctx, int tid, int unique_id, u64 epoch,
113 unsigned reuse_count,
114 uptr stk_addr, uptr stk_size,
115 uptr tls_addr, uptr tls_size)
116 : fast_state(tid, epoch)
117 // Do not touch these, rely on zero initialization,
118 // they may be accessed before the ctor.
119 // , ignore_reads_and_writes()
120 // , ignore_interceptors()
121 , clock(tid, reuse_count)
122#if !SANITIZER_GO
123 , jmp_bufs()
124#endif
125 , tid(tid)
126 , unique_id(unique_id)
127 , stk_addr(stk_addr)
128 , stk_size(stk_size)
129 , tls_addr(tls_addr)
130 , tls_size(tls_size)
131#if !SANITIZER_GO
132 , last_sleep_clock(tid)
133#endif
134{
135}
136
137#if !SANITIZER_GO
138static void MemoryProfiler(Context *ctx, fd_t fd, int i) {
139 uptr n_threads;
140 uptr n_running_threads;
141 ctx->thread_registry->GetNumberOfThreads(&n_threads, &n_running_threads);
142 InternalMmapVector<char> buf(4096);
143 WriteMemoryProfile(buf.data(), buf.size(), n_threads, n_running_threads);
144 WriteToFile(fd, buf.data(), internal_strlen(buf.data()));
145}
146
147static void *BackgroundThread(void *arg) {
148 // This is a non-initialized non-user thread, nothing to see here.
149 // We don't use ScopedIgnoreInterceptors, because we want ignores to be
150 // enabled even when the thread function exits (e.g. during pthread thread
151 // shutdown code).
152 cur_thread_init();
153 cur_thread()->ignore_interceptors++;
154 const u64 kMs2Ns = 1000 * 1000;
155
156 fd_t mprof_fd = kInvalidFd;
157 if (flags()->profile_memory && flags()->profile_memory[0]) {
158 if (internal_strcmp(flags()->profile_memory, "stdout") == 0) {
159 mprof_fd = 1;
160 } else if (internal_strcmp(flags()->profile_memory, "stderr") == 0) {
161 mprof_fd = 2;
162 } else {
163 InternalScopedString filename(kMaxPathLength);
164 filename.append("%s.%d", flags()->profile_memory, (int)internal_getpid());
165 fd_t fd = OpenFile(filename.data(), WrOnly);
166 if (fd == kInvalidFd) {
167 Printf("ThreadSanitizer: failed to open memory profile file '%s'\n",
168 &filename[0]);
169 } else {
170 mprof_fd = fd;
171 }
172 }
173 }
174
175 u64 last_flush = NanoTime();
176 uptr last_rss = 0;
177 for (int i = 0;
178 atomic_load(&ctx->stop_background_thread, memory_order_relaxed) == 0;
179 i++) {
180 SleepForMillis(100);
181 u64 now = NanoTime();
182
183 // Flush memory if requested.
184 if (flags()->flush_memory_ms > 0) {
185 if (last_flush + flags()->flush_memory_ms * kMs2Ns < now) {
186 VPrintf(1, "ThreadSanitizer: periodic memory flush\n");
187 FlushShadowMemory();
188 last_flush = NanoTime();
189 }
190 }
191 // GetRSS can be expensive on huge programs, so don't do it every 100ms.
192 if (flags()->memory_limit_mb > 0) {
193 uptr rss = GetRSS();
194 uptr limit = uptr(flags()->memory_limit_mb) << 20;
195 VPrintf(1, "ThreadSanitizer: memory flush check"
196 " RSS=%llu LAST=%llu LIMIT=%llu\n",
197 (u64)rss >> 20, (u64)last_rss >> 20, (u64)limit >> 20);
198 if (2 * rss > limit + last_rss) {
199 VPrintf(1, "ThreadSanitizer: flushing memory due to RSS\n");
200 FlushShadowMemory();
201 rss = GetRSS();
202 VPrintf(1, "ThreadSanitizer: memory flushed RSS=%llu\n", (u64)rss>>20);
203 }
204 last_rss = rss;
205 }
206
207 // Write memory profile if requested.
208 if (mprof_fd != kInvalidFd)
209 MemoryProfiler(ctx, mprof_fd, i);
210
211 // Flush symbolizer cache if requested.
212 if (flags()->flush_symbolizer_ms > 0) {
213 u64 last = atomic_load(&ctx->last_symbolize_time_ns,
214 memory_order_relaxed);
215 if (last != 0 && last + flags()->flush_symbolizer_ms * kMs2Ns < now) {
216 Lock l(&ctx->report_mtx);
217 ScopedErrorReportLock l2;
218 SymbolizeFlush();
219 atomic_store(&ctx->last_symbolize_time_ns, 0, memory_order_relaxed);
220 }
221 }
222 }
223 return nullptr;
224}
225
226static void StartBackgroundThread() {
227 ctx->background_thread = internal_start_thread(&BackgroundThread, 0);
228}
229
230#ifndef __mips__
231static void StopBackgroundThread() {
232 atomic_store(&ctx->stop_background_thread, 1, memory_order_relaxed);
233 internal_join_thread(ctx->background_thread);
234 ctx->background_thread = 0;
235}
236#endif
237#endif
238
239void DontNeedShadowFor(uptr addr, uptr size) {
240 ReleaseMemoryPagesToOS(MemToShadow(addr), MemToShadow(addr + size));
241}
242
243#if !SANITIZER_GO
244void UnmapShadow(ThreadState *thr, uptr addr, uptr size) {
245 if (size == 0) return;
246 DontNeedShadowFor(addr, size);
247 ScopedGlobalProcessor sgp;
248 ctx->metamap.ResetRange(thr->proc(), addr, size);
249}
250#endif
251
252void MapShadow(uptr addr, uptr size) {
253 // Global data is not 64K aligned, but there are no adjacent mappings,
254 // so we can get away with unaligned mapping.
255 // CHECK_EQ(addr, addr & ~((64 << 10) - 1)); // windows wants 64K alignment
256 const uptr kPageSize = GetPageSizeCached();
257 uptr shadow_begin = RoundDownTo((uptr)MemToShadow(addr), kPageSize);
258 uptr shadow_end = RoundUpTo((uptr)MemToShadow(addr + size), kPageSize);
259 if (!MmapFixedNoReserve(shadow_begin, shadow_end - shadow_begin, "shadow"))
260 Die();
261
262 // Meta shadow is 2:1, so tread carefully.
263 static bool data_mapped = false;
264 static uptr mapped_meta_end = 0;
265 uptr meta_begin = (uptr)MemToMeta(addr);
266 uptr meta_end = (uptr)MemToMeta(addr + size);
267 meta_begin = RoundDownTo(meta_begin, 64 << 10);
268 meta_end = RoundUpTo(meta_end, 64 << 10);
269 if (!data_mapped) {
270 // First call maps data+bss.
271 data_mapped = true;
272 if (!MmapFixedNoReserve(meta_begin, meta_end - meta_begin, "meta shadow"))
273 Die();
274 } else {
275 // Mapping continous heap.
276 // Windows wants 64K alignment.
277 meta_begin = RoundDownTo(meta_begin, 64 << 10);
278 meta_end = RoundUpTo(meta_end, 64 << 10);
279 if (meta_end <= mapped_meta_end)
280 return;
281 if (meta_begin < mapped_meta_end)
282 meta_begin = mapped_meta_end;
283 if (!MmapFixedNoReserve(meta_begin, meta_end - meta_begin, "meta shadow"))
284 Die();
285 mapped_meta_end = meta_end;
286 }
287 VPrintf(2, "mapped meta shadow for (%p-%p) at (%p-%p)\n",
288 addr, addr+size, meta_begin, meta_end);
289}
290
291void MapThreadTrace(uptr addr, uptr size, const char *name) {
292 DPrintf("#0: Mapping trace at %p-%p(0x%zx)\n", addr, addr + size, size);
293 CHECK_GE(addr, TraceMemBeg());
294 CHECK_LE(addr + size, TraceMemEnd());
295 CHECK_EQ(addr, addr & ~((64 << 10) - 1)); // windows wants 64K alignment
296 if (!MmapFixedNoReserve(addr, size, name)) {
297 Printf("FATAL: ThreadSanitizer can not mmap thread trace (%p/%p)\n",
298 addr, size);
299 Die();
300 }
301}
302
303static void CheckShadowMapping() {
304 uptr beg, end;
305 for (int i = 0; GetUserRegion(i, &beg, &end); i++) {
306 // Skip cases for empty regions (heap definition for architectures that
307 // do not use 64-bit allocator).
308 if (beg == end)
309 continue;
310 VPrintf(3, "checking shadow region %p-%p\n", beg, end);
311 uptr prev = 0;
312 for (uptr p0 = beg; p0 <= end; p0 += (end - beg) / 4) {
313 for (int x = -(int)kShadowCell; x <= (int)kShadowCell; x += kShadowCell) {
314 const uptr p = RoundDown(p0 + x, kShadowCell);
315 if (p < beg || p >= end)
316 continue;
317 const uptr s = MemToShadow(p);
318 const uptr m = (uptr)MemToMeta(p);
319 VPrintf(3, " checking pointer %p: shadow=%p meta=%p\n", p, s, m);
320 CHECK(IsAppMem(p));
321 CHECK(IsShadowMem(s));
322 CHECK_EQ(p, ShadowToMem(s));
323 CHECK(IsMetaMem(m));
324 if (prev) {
325 // Ensure that shadow and meta mappings are linear within a single
326 // user range. Lots of code that processes memory ranges assumes it.
327 const uptr prev_s = MemToShadow(prev);
328 const uptr prev_m = (uptr)MemToMeta(prev);
329 CHECK_EQ(s - prev_s, (p - prev) * kShadowMultiplier);
330 CHECK_EQ((m - prev_m) / kMetaShadowSize,
331 (p - prev) / kMetaShadowCell);
332 }
333 prev = p;
334 }
335 }
336 }
337}
338
339#if !SANITIZER_GO
340static void OnStackUnwind(const SignalContext &sig, const void *,
341 BufferedStackTrace *stack) {
342 stack->Unwind(StackTrace::GetNextInstructionPc(sig.pc), sig.bp, sig.context,
343 common_flags()->fast_unwind_on_fatal);
344}
345
346static void TsanOnDeadlySignal(int signo, void *siginfo, void *context) {
347 HandleDeadlySignal(siginfo, context, GetTid(), &OnStackUnwind, nullptr);
348}
349#endif
350
351void Initialize(ThreadState *thr) {
352 // Thread safe because done before all threads exist.
353 static bool is_initialized = false;
354 if (is_initialized)
355 return;
356 is_initialized = true;
357 // We are not ready to handle interceptors yet.
358 ScopedIgnoreInterceptors ignore;
359 SanitizerToolName = "ThreadSanitizer";
360 // Install tool-specific callbacks in sanitizer_common.
361 SetCheckFailedCallback(TsanCheckFailed);
362
363 ctx = new(ctx_placeholder) Context;
364 const char *env_name = SANITIZER_GO ? "GORACE" : "TSAN_OPTIONS";
365 const char *options = GetEnv(env_name);
366 CacheBinaryName();
367 CheckASLR();
368 InitializeFlags(&ctx->flags, options, env_name);
369 AvoidCVE_2016_2143();
370 __sanitizer::InitializePlatformEarly();
371 __tsan::InitializePlatformEarly();
372
373#if !SANITIZER_GO
374 // Re-exec ourselves if we need to set additional env or command line args.
375 MaybeReexec();
376
377 InitializeAllocator();
378 ReplaceSystemMalloc();
379#endif
380 if (common_flags()->detect_deadlocks)
381 ctx->dd = DDetector::Create(flags());
382 Processor *proc = ProcCreate();
383 ProcWire(proc, thr);
384 InitializeInterceptors();
385 CheckShadowMapping();
386 InitializePlatform();
387 InitializeMutex();
388 InitializeDynamicAnnotations();
389#if !SANITIZER_GO
390 InitializeShadowMemory();
391 InitializeAllocatorLate();
392 InstallDeadlySignalHandlers(TsanOnDeadlySignal);
393#endif
394 // Setup correct file descriptor for error reports.
395 __sanitizer_set_report_path(common_flags()->log_path);
396 InitializeSuppressions();
397#if !SANITIZER_GO
398 InitializeLibIgnore();
399 Symbolizer::GetOrInit()->AddHooks(EnterSymbolizer, ExitSymbolizer);
400#endif
401
402 VPrintf(1, "***** Running under ThreadSanitizer v2 (pid %d) *****\n",
403 (int)internal_getpid());
404
405 // Initialize thread 0.
406 int tid = ThreadCreate(thr, 0, 0, true);
407 CHECK_EQ(tid, 0);
408 ThreadStart(thr, tid, GetTid(), ThreadType::Regular);
409#if TSAN_CONTAINS_UBSAN
410 __ubsan::InitAsPlugin();
411#endif
412 ctx->initialized = true;
413
414#if !SANITIZER_GO
415 Symbolizer::LateInitialize();
416#endif
417
418 if (flags()->stop_on_start) {
419 Printf("ThreadSanitizer is suspended at startup (pid %d)."
420 " Call __tsan_resume().\n",
421 (int)internal_getpid());
422 while (__tsan_resumed == 0) {}
423 }
424
425 OnInitialize();
426}
427
428void MaybeSpawnBackgroundThread() {
429 // On MIPS, TSan initialization is run before
430 // __pthread_initialize_minimal_internal() is finished, so we can not spawn
431 // new threads.
432#if !SANITIZER_GO && !defined(__mips__)
433 static atomic_uint32_t bg_thread = {};
434 if (atomic_load(&bg_thread, memory_order_relaxed) == 0 &&
435 atomic_exchange(&bg_thread, 1, memory_order_relaxed) == 0) {
436 StartBackgroundThread();
437 SetSandboxingCallback(StopBackgroundThread);
438 }
439#endif
440}
441
442
443int Finalize(ThreadState *thr) {
444 bool failed = false;
445
446 if (common_flags()->print_module_map == 1) PrintModuleMap();
447
448 if (flags()->atexit_sleep_ms > 0 && ThreadCount(thr) > 1)
449 SleepForMillis(flags()->atexit_sleep_ms);
450
451 // Wait for pending reports.
452 ctx->report_mtx.Lock();
453 { ScopedErrorReportLock l; }
454 ctx->report_mtx.Unlock();
455
456#if !SANITIZER_GO
457 if (Verbosity()) AllocatorPrintStats();
458#endif
459
460 ThreadFinalize(thr);
461
462 if (ctx->nreported) {
463 failed = true;
464#if !SANITIZER_GO
465 Printf("ThreadSanitizer: reported %d warnings\n", ctx->nreported);
466#else
467 Printf("Found %d data race(s)\n", ctx->nreported);
468#endif
469 }
470
471 if (ctx->nmissed_expected) {
472 failed = true;
473 Printf("ThreadSanitizer: missed %d expected races\n",
474 ctx->nmissed_expected);
475 }
476
477 if (common_flags()->print_suppressions)
478 PrintMatchedSuppressions();
479#if !SANITIZER_GO
480 if (flags()->print_benign)
481 PrintMatchedBenignRaces();
482#endif
483
484 failed = OnFinalize(failed);
485
486#if TSAN_COLLECT_STATS
487 StatAggregate(ctx->stat, thr->stat);
488 StatOutput(ctx->stat);
489#endif
490
491 return failed ? common_flags()->exitcode : 0;
492}
493
494#if !SANITIZER_GO
495void ForkBefore(ThreadState *thr, uptr pc) {
496 ctx->thread_registry->Lock();
497 ctx->report_mtx.Lock();
498 // Ignore memory accesses in the pthread_atfork callbacks.
499 // If any of them triggers a data race we will deadlock
500 // on the report_mtx.
501 // We could ignore interceptors and sync operations as well,
502 // but so far it's unclear if it will do more good or harm.
503 // Unnecessarily ignoring things can lead to false positives later.
504 ThreadIgnoreBegin(thr, pc);
505}
506
507void ForkParentAfter(ThreadState *thr, uptr pc) {
508 ThreadIgnoreEnd(thr, pc); // Begin is in ForkBefore.
509 ctx->report_mtx.Unlock();
510 ctx->thread_registry->Unlock();
511}
512
513void ForkChildAfter(ThreadState *thr, uptr pc) {
514 ThreadIgnoreEnd(thr, pc); // Begin is in ForkBefore.
515 ctx->report_mtx.Unlock();
516 ctx->thread_registry->Unlock();
517
518 uptr nthread = 0;
519 ctx->thread_registry->GetNumberOfThreads(0, 0, &nthread /* alive threads */);
520 VPrintf(1, "ThreadSanitizer: forked new process with pid %d,"
521 " parent had %d threads\n", (int)internal_getpid(), (int)nthread);
522 if (nthread == 1) {
523 StartBackgroundThread();
524 } else {
525 // We've just forked a multi-threaded process. We cannot reasonably function
526 // after that (some mutexes may be locked before fork). So just enable
527 // ignores for everything in the hope that we will exec soon.
528 ctx->after_multithreaded_fork = true;
529 thr->ignore_interceptors++;
530 ThreadIgnoreBegin(thr, pc);
531 ThreadIgnoreSyncBegin(thr, pc);
532 }
533}
534#endif
535
536#if SANITIZER_GO
537NOINLINE
538void GrowShadowStack(ThreadState *thr) {
539 const int sz = thr->shadow_stack_end - thr->shadow_stack;
540 const int newsz = 2 * sz;
541 uptr *newstack = (uptr*)internal_alloc(MBlockShadowStack,
542 newsz * sizeof(uptr));
543 internal_memcpy(newstack, thr->shadow_stack, sz * sizeof(uptr));
544 internal_free(thr->shadow_stack);
545 thr->shadow_stack = newstack;
546 thr->shadow_stack_pos = newstack + sz;
547 thr->shadow_stack_end = newstack + newsz;
548}
549#endif
550
551u32 CurrentStackId(ThreadState *thr, uptr pc) {
552 if (!thr->is_inited) // May happen during bootstrap.
553 return 0;
554 if (pc != 0) {
555#if !SANITIZER_GO
556 DCHECK_LT(thr->shadow_stack_pos, thr->shadow_stack_end);
557#else
558 if (thr->shadow_stack_pos == thr->shadow_stack_end)
559 GrowShadowStack(thr);
560#endif
561 thr->shadow_stack_pos[0] = pc;
562 thr->shadow_stack_pos++;
563 }
564 u32 id = StackDepotPut(
565 StackTrace(thr->shadow_stack, thr->shadow_stack_pos - thr->shadow_stack));
566 if (pc != 0)
567 thr->shadow_stack_pos--;
568 return id;
569}
570
571void TraceSwitch(ThreadState *thr) {
572#if !SANITIZER_GO
573 if (ctx->after_multithreaded_fork)
574 return;
575#endif
576 thr->nomalloc++;
577 Trace *thr_trace = ThreadTrace(thr->tid);
578 Lock l(&thr_trace->mtx);
579 unsigned trace = (thr->fast_state.epoch() / kTracePartSize) % TraceParts();
580 TraceHeader *hdr = &thr_trace->headers[trace];
581 hdr->epoch0 = thr->fast_state.epoch();
582 ObtainCurrentStack(thr, 0, &hdr->stack0);
583 hdr->mset0 = thr->mset;
584 thr->nomalloc--;
585}
586
587Trace *ThreadTrace(int tid) {
588 return (Trace*)GetThreadTraceHeader(tid);
589}
590
591uptr TraceTopPC(ThreadState *thr) {
592 Event *events = (Event*)GetThreadTrace(thr->tid);
593 uptr pc = events[thr->fast_state.GetTracePos()];
594 return pc;
595}
596
597uptr TraceSize() {
598 return (uptr)(1ull << (kTracePartSizeBits + flags()->history_size + 1));
599}
600
601uptr TraceParts() {
602 return TraceSize() / kTracePartSize;
603}
604
605#if !SANITIZER_GO
606extern "C" void __tsan_trace_switch() {
607 TraceSwitch(cur_thread());
608}
609
610extern "C" void __tsan_report_race() {
611 ReportRace(cur_thread());
612}
613#endif
614
615ALWAYS_INLINE
616Shadow LoadShadow(u64 *p) {
617 u64 raw = atomic_load((atomic_uint64_t*)p, memory_order_relaxed);
618 return Shadow(raw);
619}
620
621ALWAYS_INLINE
622void StoreShadow(u64 *sp, u64 s) {
623 atomic_store((atomic_uint64_t*)sp, s, memory_order_relaxed);
624}
625
626ALWAYS_INLINE
627void StoreIfNotYetStored(u64 *sp, u64 *s) {
628 StoreShadow(sp, *s);
629 *s = 0;
630}
631
632ALWAYS_INLINE
633void HandleRace(ThreadState *thr, u64 *shadow_mem,
634 Shadow cur, Shadow old) {
635 thr->racy_state[0] = cur.raw();
636 thr->racy_state[1] = old.raw();
637 thr->racy_shadow_addr = shadow_mem;
638#if !SANITIZER_GO
639 HACKY_CALL(__tsan_report_race);
640#else
641 ReportRace(thr);
642#endif
643}
644
645static inline bool HappensBefore(Shadow old, ThreadState *thr) {
646 return thr->clock.get(old.TidWithIgnore()) >= old.epoch();
647}
648
649ALWAYS_INLINE
650void MemoryAccessImpl1(ThreadState *thr, uptr addr,
651 int kAccessSizeLog, bool kAccessIsWrite, bool kIsAtomic,
652 u64 *shadow_mem, Shadow cur) {
653 StatInc(thr, StatMop);
654 StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead);
655 StatInc(thr, (StatType)(StatMop1 + kAccessSizeLog));
656
657 // This potentially can live in an MMX/SSE scratch register.
658 // The required intrinsics are:
659 // __m128i _mm_move_epi64(__m128i*);
660 // _mm_storel_epi64(u64*, __m128i);
661 u64 store_word = cur.raw();
662 bool stored = false;
663
664 // scan all the shadow values and dispatch to 4 categories:
665 // same, replace, candidate and race (see comments below).
666 // we consider only 3 cases regarding access sizes:
667 // equal, intersect and not intersect. initially I considered
668 // larger and smaller as well, it allowed to replace some
669 // 'candidates' with 'same' or 'replace', but I think
670 // it's just not worth it (performance- and complexity-wise).
671
672 Shadow old(0);
673
674 // It release mode we manually unroll the loop,
675 // because empirically gcc generates better code this way.
676 // However, we can't afford unrolling in debug mode, because the function
677 // consumes almost 4K of stack. Gtest gives only 4K of stack to death test
678 // threads, which is not enough for the unrolled loop.
679#if SANITIZER_DEBUG
680 for (int idx = 0; idx < 4; idx++) {
681#include "tsan_update_shadow_word_inl.h"
682 }
683#else
684 int idx = 0;
685#include "tsan_update_shadow_word_inl.h"
686 idx = 1;
687 if (stored) {
688#include "tsan_update_shadow_word_inl.h"
689 } else {
690#include "tsan_update_shadow_word_inl.h"
691 }
692 idx = 2;
693 if (stored) {
694#include "tsan_update_shadow_word_inl.h"
695 } else {
696#include "tsan_update_shadow_word_inl.h"
697 }
698 idx = 3;
699 if (stored) {
700#include "tsan_update_shadow_word_inl.h"
701 } else {
702#include "tsan_update_shadow_word_inl.h"
703 }
704#endif
705
706 // we did not find any races and had already stored
707 // the current access info, so we are done
708 if (LIKELY(stored))
709 return;
710 // choose a random candidate slot and replace it
711 StoreShadow(shadow_mem + (cur.epoch() % kShadowCnt), store_word);
712 StatInc(thr, StatShadowReplace);
713 return;
714 RACE:
715 HandleRace(thr, shadow_mem, cur, old);
716 return;
717}
718
719void UnalignedMemoryAccess(ThreadState *thr, uptr pc, uptr addr,
720 int size, bool kAccessIsWrite, bool kIsAtomic) {
721 while (size) {
722 int size1 = 1;
723 int kAccessSizeLog = kSizeLog1;
724 if (size >= 8 && (addr & ~7) == ((addr + 7) & ~7)) {
725 size1 = 8;
726 kAccessSizeLog = kSizeLog8;
727 } else if (size >= 4 && (addr & ~7) == ((addr + 3) & ~7)) {
728 size1 = 4;
729 kAccessSizeLog = kSizeLog4;
730 } else if (size >= 2 && (addr & ~7) == ((addr + 1) & ~7)) {
731 size1 = 2;
732 kAccessSizeLog = kSizeLog2;
733 }
734 MemoryAccess(thr, pc, addr, kAccessSizeLog, kAccessIsWrite, kIsAtomic);
735 addr += size1;
736 size -= size1;
737 }
738}
739
740ALWAYS_INLINE
741bool ContainsSameAccessSlow(u64 *s, u64 a, u64 sync_epoch, bool is_write) {
742 Shadow cur(a);
743 for (uptr i = 0; i < kShadowCnt; i++) {
744 Shadow old(LoadShadow(&s[i]));
745 if (Shadow::Addr0AndSizeAreEqual(cur, old) &&
746 old.TidWithIgnore() == cur.TidWithIgnore() &&
747 old.epoch() > sync_epoch &&
748 old.IsAtomic() == cur.IsAtomic() &&
749 old.IsRead() <= cur.IsRead())
750 return true;
751 }
752 return false;
753}
754
755#if defined(__SSE3__)
756#define SHUF(v0, v1, i0, i1, i2, i3) _mm_castps_si128(_mm_shuffle_ps( \
757 _mm_castsi128_ps(v0), _mm_castsi128_ps(v1), \
758 (i0)*1 + (i1)*4 + (i2)*16 + (i3)*64))
759ALWAYS_INLINE
760bool ContainsSameAccessFast(u64 *s, u64 a, u64 sync_epoch, bool is_write) {
761 // This is an optimized version of ContainsSameAccessSlow.
762 // load current access into access[0:63]
763 const m128 access = _mm_cvtsi64_si128(a);
764 // duplicate high part of access in addr0:
765 // addr0[0:31] = access[32:63]
766 // addr0[32:63] = access[32:63]
767 // addr0[64:95] = access[32:63]
768 // addr0[96:127] = access[32:63]
769 const m128 addr0 = SHUF(access, access, 1, 1, 1, 1);
770 // load 4 shadow slots
771 const m128 shadow0 = _mm_load_si128((__m128i*)s);
772 const m128 shadow1 = _mm_load_si128((__m128i*)s + 1);
773 // load high parts of 4 shadow slots into addr_vect:
774 // addr_vect[0:31] = shadow0[32:63]
775 // addr_vect[32:63] = shadow0[96:127]
776 // addr_vect[64:95] = shadow1[32:63]
777 // addr_vect[96:127] = shadow1[96:127]
778 m128 addr_vect = SHUF(shadow0, shadow1, 1, 3, 1, 3);
779 if (!is_write) {
780 // set IsRead bit in addr_vect
781 const m128 rw_mask1 = _mm_cvtsi64_si128(1<<15);
782 const m128 rw_mask = SHUF(rw_mask1, rw_mask1, 0, 0, 0, 0);
783 addr_vect = _mm_or_si128(addr_vect, rw_mask);
784 }
785 // addr0 == addr_vect?
786 const m128 addr_res = _mm_cmpeq_epi32(addr0, addr_vect);
787 // epoch1[0:63] = sync_epoch
788 const m128 epoch1 = _mm_cvtsi64_si128(sync_epoch);
789 // epoch[0:31] = sync_epoch[0:31]
790 // epoch[32:63] = sync_epoch[0:31]
791 // epoch[64:95] = sync_epoch[0:31]
792 // epoch[96:127] = sync_epoch[0:31]
793 const m128 epoch = SHUF(epoch1, epoch1, 0, 0, 0, 0);
794 // load low parts of shadow cell epochs into epoch_vect:
795 // epoch_vect[0:31] = shadow0[0:31]
796 // epoch_vect[32:63] = shadow0[64:95]
797 // epoch_vect[64:95] = shadow1[0:31]
798 // epoch_vect[96:127] = shadow1[64:95]
799 const m128 epoch_vect = SHUF(shadow0, shadow1, 0, 2, 0, 2);
800 // epoch_vect >= sync_epoch?
801 const m128 epoch_res = _mm_cmpgt_epi32(epoch_vect, epoch);
802 // addr_res & epoch_res
803 const m128 res = _mm_and_si128(addr_res, epoch_res);
804 // mask[0] = res[7]
805 // mask[1] = res[15]
806 // ...
807 // mask[15] = res[127]
808 const int mask = _mm_movemask_epi8(res);
809 return mask != 0;
810}
811#endif
812
813ALWAYS_INLINE
814bool ContainsSameAccess(u64 *s, u64 a, u64 sync_epoch, bool is_write) {
815#if defined(__SSE3__)
816 bool res = ContainsSameAccessFast(s, a, sync_epoch, is_write);
817 // NOTE: this check can fail if the shadow is concurrently mutated
818 // by other threads. But it still can be useful if you modify
819 // ContainsSameAccessFast and want to ensure that it's not completely broken.
820 // DCHECK_EQ(res, ContainsSameAccessSlow(s, a, sync_epoch, is_write));
821 return res;
822#else
823 return ContainsSameAccessSlow(s, a, sync_epoch, is_write);
824#endif
825}
826
827ALWAYS_INLINE USED
828void MemoryAccess(ThreadState *thr, uptr pc, uptr addr,
829 int kAccessSizeLog, bool kAccessIsWrite, bool kIsAtomic) {
830 u64 *shadow_mem = (u64*)MemToShadow(addr);
831 DPrintf2("#%d: MemoryAccess: @%p %p size=%d"
832 " is_write=%d shadow_mem=%p {%zx, %zx, %zx, %zx}\n",
833 (int)thr->fast_state.tid(), (void*)pc, (void*)addr,
834 (int)(1 << kAccessSizeLog), kAccessIsWrite, shadow_mem,
835 (uptr)shadow_mem[0], (uptr)shadow_mem[1],
836 (uptr)shadow_mem[2], (uptr)shadow_mem[3]);
837#if SANITIZER_DEBUG
838 if (!IsAppMem(addr)) {
839 Printf("Access to non app mem %zx\n", addr);
840 DCHECK(IsAppMem(addr));
841 }
842 if (!IsShadowMem((uptr)shadow_mem)) {
843 Printf("Bad shadow addr %p (%zx)\n", shadow_mem, addr);
844 DCHECK(IsShadowMem((uptr)shadow_mem));
845 }
846#endif
847
848 if (!SANITIZER_GO && !kAccessIsWrite && *shadow_mem == kShadowRodata) {
849 // Access to .rodata section, no races here.
850 // Measurements show that it can be 10-20% of all memory accesses.
851 StatInc(thr, StatMop);
852 StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead);
853 StatInc(thr, (StatType)(StatMop1 + kAccessSizeLog));
854 StatInc(thr, StatMopRodata);
855 return;
856 }
857
858 FastState fast_state = thr->fast_state;
859 if (UNLIKELY(fast_state.GetIgnoreBit())) {
860 StatInc(thr, StatMop);
861 StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead);
862 StatInc(thr, (StatType)(StatMop1 + kAccessSizeLog));
863 StatInc(thr, StatMopIgnored);
864 return;
865 }
866
867 Shadow cur(fast_state);
868 cur.SetAddr0AndSizeLog(addr & 7, kAccessSizeLog);
869 cur.SetWrite(kAccessIsWrite);
870 cur.SetAtomic(kIsAtomic);
871
872 if (LIKELY(ContainsSameAccess(shadow_mem, cur.raw(),
873 thr->fast_synch_epoch, kAccessIsWrite))) {
874 StatInc(thr, StatMop);
875 StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead);
876 StatInc(thr, (StatType)(StatMop1 + kAccessSizeLog));
877 StatInc(thr, StatMopSame);
878 return;
879 }
880
881 if (kCollectHistory) {
882 fast_state.IncrementEpoch();
883 thr->fast_state = fast_state;
884 TraceAddEvent(thr, fast_state, EventTypeMop, pc);
885 cur.IncrementEpoch();
886 }
887
888 MemoryAccessImpl1(thr, addr, kAccessSizeLog, kAccessIsWrite, kIsAtomic,
889 shadow_mem, cur);
890}
891
892// Called by MemoryAccessRange in tsan_rtl_thread.cpp
893ALWAYS_INLINE USED
894void MemoryAccessImpl(ThreadState *thr, uptr addr,
895 int kAccessSizeLog, bool kAccessIsWrite, bool kIsAtomic,
896 u64 *shadow_mem, Shadow cur) {
897 if (LIKELY(ContainsSameAccess(shadow_mem, cur.raw(),
898 thr->fast_synch_epoch, kAccessIsWrite))) {
899 StatInc(thr, StatMop);
900 StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead);
901 StatInc(thr, (StatType)(StatMop1 + kAccessSizeLog));
902 StatInc(thr, StatMopSame);
903 return;
904 }
905
906 MemoryAccessImpl1(thr, addr, kAccessSizeLog, kAccessIsWrite, kIsAtomic,
907 shadow_mem, cur);
908}
909
910static void MemoryRangeSet(ThreadState *thr, uptr pc, uptr addr, uptr size,
911 u64 val) {
912 (void)thr;
913 (void)pc;
914 if (size == 0)
915 return;
916 // FIXME: fix me.
917 uptr offset = addr % kShadowCell;
918 if (offset) {
919 offset = kShadowCell - offset;
920 if (size <= offset)
921 return;
922 addr += offset;
923 size -= offset;
924 }
925 DCHECK_EQ(addr % 8, 0);
926 // If a user passes some insane arguments (memset(0)),
927 // let it just crash as usual.
928 if (!IsAppMem(addr) || !IsAppMem(addr + size - 1))
929 return;
930 // Don't want to touch lots of shadow memory.
931 // If a program maps 10MB stack, there is no need reset the whole range.
932 size = (size + (kShadowCell - 1)) & ~(kShadowCell - 1);
933 // UnmapOrDie/MmapFixedNoReserve does not work on Windows.
934 if (SANITIZER_WINDOWS || size < common_flags()->clear_shadow_mmap_threshold) {
935 u64 *p = (u64*)MemToShadow(addr);
936 CHECK(IsShadowMem((uptr)p));
937 CHECK(IsShadowMem((uptr)(p + size * kShadowCnt / kShadowCell - 1)));
938 // FIXME: may overwrite a part outside the region
939 for (uptr i = 0; i < size / kShadowCell * kShadowCnt;) {
940 p[i++] = val;
941 for (uptr j = 1; j < kShadowCnt; j++)
942 p[i++] = 0;
943 }
944 } else {
945 // The region is big, reset only beginning and end.
946 const uptr kPageSize = GetPageSizeCached();
947 u64 *begin = (u64*)MemToShadow(addr);
948 u64 *end = begin + size / kShadowCell * kShadowCnt;
949 u64 *p = begin;
950 // Set at least first kPageSize/2 to page boundary.
951 while ((p < begin + kPageSize / kShadowSize / 2) || ((uptr)p % kPageSize)) {
952 *p++ = val;
953 for (uptr j = 1; j < kShadowCnt; j++)
954 *p++ = 0;
955 }
956 // Reset middle part.
957 u64 *p1 = p;
958 p = RoundDown(end, kPageSize);
959 UnmapOrDie((void*)p1, (uptr)p - (uptr)p1);
960 if (!MmapFixedNoReserve((uptr)p1, (uptr)p - (uptr)p1))
961 Die();
962 // Set the ending.
963 while (p < end) {
964 *p++ = val;
965 for (uptr j = 1; j < kShadowCnt; j++)
966 *p++ = 0;
967 }
968 }
969}
970
971void MemoryResetRange(ThreadState *thr, uptr pc, uptr addr, uptr size) {
972 MemoryRangeSet(thr, pc, addr, size, 0);
973}
974
975void MemoryRangeFreed(ThreadState *thr, uptr pc, uptr addr, uptr size) {
976 // Processing more than 1k (4k of shadow) is expensive,
977 // can cause excessive memory consumption (user does not necessary touch
978 // the whole range) and most likely unnecessary.
979 if (size > 1024)
980 size = 1024;
981 CHECK_EQ(thr->is_freeing, false);
982 thr->is_freeing = true;
983 MemoryAccessRange(thr, pc, addr, size, true);
984 thr->is_freeing = false;
985 if (kCollectHistory) {
986 thr->fast_state.IncrementEpoch();
987 TraceAddEvent(thr, thr->fast_state, EventTypeMop, pc);
988 }
989 Shadow s(thr->fast_state);
990 s.ClearIgnoreBit();
991 s.MarkAsFreed();
992 s.SetWrite(true);
993 s.SetAddr0AndSizeLog(0, 3);
994 MemoryRangeSet(thr, pc, addr, size, s.raw());
995}
996
997void MemoryRangeImitateWrite(ThreadState *thr, uptr pc, uptr addr, uptr size) {
998 if (kCollectHistory) {
999 thr->fast_state.IncrementEpoch();
1000 TraceAddEvent(thr, thr->fast_state, EventTypeMop, pc);
1001 }
1002 Shadow s(thr->fast_state);
1003 s.ClearIgnoreBit();
1004 s.SetWrite(true);
1005 s.SetAddr0AndSizeLog(0, 3);
1006 MemoryRangeSet(thr, pc, addr, size, s.raw());
1007}
1008
1009void MemoryRangeImitateWriteOrResetRange(ThreadState *thr, uptr pc, uptr addr,
1010 uptr size) {
1011 if (thr->ignore_reads_and_writes == 0)
1012 MemoryRangeImitateWrite(thr, pc, addr, size);
1013 else
1014 MemoryResetRange(thr, pc, addr, size);
1015}
1016
1017ALWAYS_INLINE USED
1018void FuncEntry(ThreadState *thr, uptr pc) {
1019 StatInc(thr, StatFuncEnter);
1020 DPrintf2("#%d: FuncEntry %p\n", (int)thr->fast_state.tid(), (void*)pc);
1021 if (kCollectHistory) {
1022 thr->fast_state.IncrementEpoch();
1023 TraceAddEvent(thr, thr->fast_state, EventTypeFuncEnter, pc);
1024 }
1025
1026 // Shadow stack maintenance can be replaced with
1027 // stack unwinding during trace switch (which presumably must be faster).
1028 DCHECK_GE(thr->shadow_stack_pos, thr->shadow_stack);
1029#if !SANITIZER_GO
1030 DCHECK_LT(thr->shadow_stack_pos, thr->shadow_stack_end);
1031#else
1032 if (thr->shadow_stack_pos == thr->shadow_stack_end)
1033 GrowShadowStack(thr);
1034#endif
1035 thr->shadow_stack_pos[0] = pc;
1036 thr->shadow_stack_pos++;
1037}
1038
1039ALWAYS_INLINE USED
1040void FuncExit(ThreadState *thr) {
1041 StatInc(thr, StatFuncExit);
1042 DPrintf2("#%d: FuncExit\n", (int)thr->fast_state.tid());
1043 if (kCollectHistory) {
1044 thr->fast_state.IncrementEpoch();
1045 TraceAddEvent(thr, thr->fast_state, EventTypeFuncExit, 0);
1046 }
1047
1048 DCHECK_GT(thr->shadow_stack_pos, thr->shadow_stack);
1049#if !SANITIZER_GO
1050 DCHECK_LT(thr->shadow_stack_pos, thr->shadow_stack_end);
1051#endif
1052 thr->shadow_stack_pos--;
1053}
1054
1055void ThreadIgnoreBegin(ThreadState *thr, uptr pc, bool save_stack) {
1056 DPrintf("#%d: ThreadIgnoreBegin\n", thr->tid);
1057 thr->ignore_reads_and_writes++;
1058 CHECK_GT(thr->ignore_reads_and_writes, 0);
1059 thr->fast_state.SetIgnoreBit();
1060#if !SANITIZER_GO
1061 if (save_stack && !ctx->after_multithreaded_fork)
1062 thr->mop_ignore_set.Add(CurrentStackId(thr, pc));
1063#endif
1064}
1065
1066void ThreadIgnoreEnd(ThreadState *thr, uptr pc) {
1067 DPrintf("#%d: ThreadIgnoreEnd\n", thr->tid);
1068 CHECK_GT(thr->ignore_reads_and_writes, 0);
1069 thr->ignore_reads_and_writes--;
1070 if (thr->ignore_reads_and_writes == 0) {
1071 thr->fast_state.ClearIgnoreBit();
1072#if !SANITIZER_GO
1073 thr->mop_ignore_set.Reset();
1074#endif
1075 }
1076}
1077
1078#if !SANITIZER_GO
1079extern "C" SANITIZER_INTERFACE_ATTRIBUTE
1080uptr __tsan_testonly_shadow_stack_current_size() {
1081 ThreadState *thr = cur_thread();
1082 return thr->shadow_stack_pos - thr->shadow_stack;
1083}
1084#endif
1085
1086void ThreadIgnoreSyncBegin(ThreadState *thr, uptr pc, bool save_stack) {
1087 DPrintf("#%d: ThreadIgnoreSyncBegin\n", thr->tid);
1088 thr->ignore_sync++;
1089 CHECK_GT(thr->ignore_sync, 0);
1090#if !SANITIZER_GO
1091 if (save_stack && !ctx->after_multithreaded_fork)
1092 thr->sync_ignore_set.Add(CurrentStackId(thr, pc));
1093#endif
1094}
1095
1096void ThreadIgnoreSyncEnd(ThreadState *thr, uptr pc) {
1097 DPrintf("#%d: ThreadIgnoreSyncEnd\n", thr->tid);
1098 CHECK_GT(thr->ignore_sync, 0);
1099 thr->ignore_sync--;
1100#if !SANITIZER_GO
1101 if (thr->ignore_sync == 0)
1102 thr->sync_ignore_set.Reset();
1103#endif
1104}
1105
1106bool MD5Hash::operator==(const MD5Hash &other) const {
1107 return hash[0] == other.hash[0] && hash[1] == other.hash[1];
1108}
1109
1110#if SANITIZER_DEBUG
1111void build_consistency_debug() {}
1112#else
1113void build_consistency_release() {}
1114#endif
1115
1116#if TSAN_COLLECT_STATS
1117void build_consistency_stats() {}
1118#else
1119void build_consistency_nostats() {}
1120#endif
1121
1122} // namespace __tsan
1123
1124#if !SANITIZER_GO
1125// Must be included in this file to make sure everything is inlined.
1126#include "tsan_interface_inl.h"
1127#endif
lib/tsan/tsan_rtl.h created+893
...@@ -0,0 +1,893 @@
1//===-- tsan_rtl.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// Main internal TSan header file.
12//
13// Ground rules:
14// - C++ run-time should not be used (static CTORs, RTTI, exceptions, static
15// function-scope locals)
16// - All functions/classes/etc reside in namespace __tsan, except for those
17// declared in tsan_interface.h.
18// - Platform-specific files should be used instead of ifdefs (*).
19// - No system headers included in header files (*).
20// - Platform specific headres included only into platform-specific files (*).
21//
22// (*) Except when inlining is critical for performance.
23//===----------------------------------------------------------------------===//
24
25#ifndef TSAN_RTL_H
26#define TSAN_RTL_H
27
28#include "sanitizer_common/sanitizer_allocator.h"
29#include "sanitizer_common/sanitizer_allocator_internal.h"
30#include "sanitizer_common/sanitizer_asm.h"
31#include "sanitizer_common/sanitizer_common.h"
32#include "sanitizer_common/sanitizer_deadlock_detector_interface.h"
33#include "sanitizer_common/sanitizer_libignore.h"
34#include "sanitizer_common/sanitizer_suppressions.h"
35#include "sanitizer_common/sanitizer_thread_registry.h"
36#include "sanitizer_common/sanitizer_vector.h"
37#include "tsan_clock.h"
38#include "tsan_defs.h"
39#include "tsan_flags.h"
40#include "tsan_mman.h"
41#include "tsan_sync.h"
42#include "tsan_trace.h"
43#include "tsan_report.h"
44#include "tsan_platform.h"
45#include "tsan_mutexset.h"
46#include "tsan_ignoreset.h"
47#include "tsan_stack_trace.h"
48
49#if SANITIZER_WORDSIZE != 64
50# error "ThreadSanitizer is supported only on 64-bit platforms"
51#endif
52
53namespace __tsan {
54
55#if !SANITIZER_GO
56struct MapUnmapCallback;
57#if defined(__mips64) || defined(__aarch64__) || defined(__powerpc__)
58
59struct AP32 {
60 static const uptr kSpaceBeg = 0;
61 static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE;
62 static const uptr kMetadataSize = 0;
63 typedef __sanitizer::CompactSizeClassMap SizeClassMap;
64 static const uptr kRegionSizeLog = 20;
65 using AddressSpaceView = LocalAddressSpaceView;
66 typedef __tsan::MapUnmapCallback MapUnmapCallback;
67 static const uptr kFlags = 0;
68};
69typedef SizeClassAllocator32<AP32> PrimaryAllocator;
70#else
71struct AP64 { // Allocator64 parameters. Deliberately using a short name.
72 static const uptr kSpaceBeg = Mapping::kHeapMemBeg;
73 static const uptr kSpaceSize = Mapping::kHeapMemEnd - Mapping::kHeapMemBeg;
74 static const uptr kMetadataSize = 0;
75 typedef DefaultSizeClassMap SizeClassMap;
76 typedef __tsan::MapUnmapCallback MapUnmapCallback;
77 static const uptr kFlags = 0;
78 using AddressSpaceView = LocalAddressSpaceView;
79};
80typedef SizeClassAllocator64<AP64> PrimaryAllocator;
81#endif
82typedef CombinedAllocator<PrimaryAllocator> Allocator;
83typedef Allocator::AllocatorCache AllocatorCache;
84Allocator *allocator();
85#endif
86
87void TsanCheckFailed(const char *file, int line, const char *cond,
88 u64 v1, u64 v2);
89
90const u64 kShadowRodata = (u64)-1; // .rodata shadow marker
91
92// FastState (from most significant bit):
93// ignore : 1
94// tid : kTidBits
95// unused : -
96// history_size : 3
97// epoch : kClkBits
98class FastState {
99 public:
100 FastState(u64 tid, u64 epoch) {
101 x_ = tid << kTidShift;
102 x_ |= epoch;
103 DCHECK_EQ(tid, this->tid());
104 DCHECK_EQ(epoch, this->epoch());
105 DCHECK_EQ(GetIgnoreBit(), false);
106 }
107
108 explicit FastState(u64 x)
109 : x_(x) {
110 }
111
112 u64 raw() const {
113 return x_;
114 }
115
116 u64 tid() const {
117 u64 res = (x_ & ~kIgnoreBit) >> kTidShift;
118 return res;
119 }
120
121 u64 TidWithIgnore() const {
122 u64 res = x_ >> kTidShift;
123 return res;
124 }
125
126 u64 epoch() const {
127 u64 res = x_ & ((1ull << kClkBits) - 1);
128 return res;
129 }
130
131 void IncrementEpoch() {
132 u64 old_epoch = epoch();
133 x_ += 1;
134 DCHECK_EQ(old_epoch + 1, epoch());
135 (void)old_epoch;
136 }
137
138 void SetIgnoreBit() { x_ |= kIgnoreBit; }
139 void ClearIgnoreBit() { x_ &= ~kIgnoreBit; }
140 bool GetIgnoreBit() const { return (s64)x_ < 0; }
141
142 void SetHistorySize(int hs) {
143 CHECK_GE(hs, 0);
144 CHECK_LE(hs, 7);
145 x_ = (x_ & ~(kHistoryMask << kHistoryShift)) | (u64(hs) << kHistoryShift);
146 }
147
148 ALWAYS_INLINE
149 int GetHistorySize() const {
150 return (int)((x_ >> kHistoryShift) & kHistoryMask);
151 }
152
153 void ClearHistorySize() {
154 SetHistorySize(0);
155 }
156
157 ALWAYS_INLINE
158 u64 GetTracePos() const {
159 const int hs = GetHistorySize();
160 // When hs == 0, the trace consists of 2 parts.
161 const u64 mask = (1ull << (kTracePartSizeBits + hs + 1)) - 1;
162 return epoch() & mask;
163 }
164
165 private:
166 friend class Shadow;
167 static const int kTidShift = 64 - kTidBits - 1;
168 static const u64 kIgnoreBit = 1ull << 63;
169 static const u64 kFreedBit = 1ull << 63;
170 static const u64 kHistoryShift = kClkBits;
171 static const u64 kHistoryMask = 7;
172 u64 x_;
173};
174
175// Shadow (from most significant bit):
176// freed : 1
177// tid : kTidBits
178// is_atomic : 1
179// is_read : 1
180// size_log : 2
181// addr0 : 3
182// epoch : kClkBits
183class Shadow : public FastState {
184 public:
185 explicit Shadow(u64 x)
186 : FastState(x) {
187 }
188
189 explicit Shadow(const FastState &s)
190 : FastState(s.x_) {
191 ClearHistorySize();
192 }
193
194 void SetAddr0AndSizeLog(u64 addr0, unsigned kAccessSizeLog) {
195 DCHECK_EQ((x_ >> kClkBits) & 31, 0);
196 DCHECK_LE(addr0, 7);
197 DCHECK_LE(kAccessSizeLog, 3);
198 x_ |= ((kAccessSizeLog << 3) | addr0) << kClkBits;
199 DCHECK_EQ(kAccessSizeLog, size_log());
200 DCHECK_EQ(addr0, this->addr0());
201 }
202
203 void SetWrite(unsigned kAccessIsWrite) {
204 DCHECK_EQ(x_ & kReadBit, 0);
205 if (!kAccessIsWrite)
206 x_ |= kReadBit;
207 DCHECK_EQ(kAccessIsWrite, IsWrite());
208 }
209
210 void SetAtomic(bool kIsAtomic) {
211 DCHECK(!IsAtomic());
212 if (kIsAtomic)
213 x_ |= kAtomicBit;
214 DCHECK_EQ(IsAtomic(), kIsAtomic);
215 }
216
217 bool IsAtomic() const {
218 return x_ & kAtomicBit;
219 }
220
221 bool IsZero() const {
222 return x_ == 0;
223 }
224
225 static inline bool TidsAreEqual(const Shadow s1, const Shadow s2) {
226 u64 shifted_xor = (s1.x_ ^ s2.x_) >> kTidShift;
227 DCHECK_EQ(shifted_xor == 0, s1.TidWithIgnore() == s2.TidWithIgnore());
228 return shifted_xor == 0;
229 }
230
231 static ALWAYS_INLINE
232 bool Addr0AndSizeAreEqual(const Shadow s1, const Shadow s2) {
233 u64 masked_xor = ((s1.x_ ^ s2.x_) >> kClkBits) & 31;
234 return masked_xor == 0;
235 }
236
237 static ALWAYS_INLINE bool TwoRangesIntersect(Shadow s1, Shadow s2,
238 unsigned kS2AccessSize) {
239 bool res = false;
240 u64 diff = s1.addr0() - s2.addr0();
241 if ((s64)diff < 0) { // s1.addr0 < s2.addr0
242 // if (s1.addr0() + size1) > s2.addr0()) return true;
243 if (s1.size() > -diff)
244 res = true;
245 } else {
246 // if (s2.addr0() + kS2AccessSize > s1.addr0()) return true;
247 if (kS2AccessSize > diff)
248 res = true;
249 }
250 DCHECK_EQ(res, TwoRangesIntersectSlow(s1, s2));
251 DCHECK_EQ(res, TwoRangesIntersectSlow(s2, s1));
252 return res;
253 }
254
255 u64 ALWAYS_INLINE addr0() const { return (x_ >> kClkBits) & 7; }
256 u64 ALWAYS_INLINE size() const { return 1ull << size_log(); }
257 bool ALWAYS_INLINE IsWrite() const { return !IsRead(); }
258 bool ALWAYS_INLINE IsRead() const { return x_ & kReadBit; }
259
260 // The idea behind the freed bit is as follows.
261 // When the memory is freed (or otherwise unaccessible) we write to the shadow
262 // values with tid/epoch related to the free and the freed bit set.
263 // During memory accesses processing the freed bit is considered
264 // as msb of tid. So any access races with shadow with freed bit set
265 // (it is as if write from a thread with which we never synchronized before).
266 // This allows us to detect accesses to freed memory w/o additional
267 // overheads in memory access processing and at the same time restore
268 // tid/epoch of free.
269 void MarkAsFreed() {
270 x_ |= kFreedBit;
271 }
272
273 bool IsFreed() const {
274 return x_ & kFreedBit;
275 }
276
277 bool GetFreedAndReset() {
278 bool res = x_ & kFreedBit;
279 x_ &= ~kFreedBit;
280 return res;
281 }
282
283 bool ALWAYS_INLINE IsBothReadsOrAtomic(bool kIsWrite, bool kIsAtomic) const {
284 bool v = x_ & ((u64(kIsWrite ^ 1) << kReadShift)
285 | (u64(kIsAtomic) << kAtomicShift));
286 DCHECK_EQ(v, (!IsWrite() && !kIsWrite) || (IsAtomic() && kIsAtomic));
287 return v;
288 }
289
290 bool ALWAYS_INLINE IsRWNotWeaker(bool kIsWrite, bool kIsAtomic) const {
291 bool v = ((x_ >> kReadShift) & 3)
292 <= u64((kIsWrite ^ 1) | (kIsAtomic << 1));
293 DCHECK_EQ(v, (IsAtomic() < kIsAtomic) ||
294 (IsAtomic() == kIsAtomic && !IsWrite() <= !kIsWrite));
295 return v;
296 }
297
298 bool ALWAYS_INLINE IsRWWeakerOrEqual(bool kIsWrite, bool kIsAtomic) const {
299 bool v = ((x_ >> kReadShift) & 3)
300 >= u64((kIsWrite ^ 1) | (kIsAtomic << 1));
301 DCHECK_EQ(v, (IsAtomic() > kIsAtomic) ||
302 (IsAtomic() == kIsAtomic && !IsWrite() >= !kIsWrite));
303 return v;
304 }
305
306 private:
307 static const u64 kReadShift = 5 + kClkBits;
308 static const u64 kReadBit = 1ull << kReadShift;
309 static const u64 kAtomicShift = 6 + kClkBits;
310 static const u64 kAtomicBit = 1ull << kAtomicShift;
311
312 u64 size_log() const { return (x_ >> (3 + kClkBits)) & 3; }
313
314 static bool TwoRangesIntersectSlow(const Shadow s1, const Shadow s2) {
315 if (s1.addr0() == s2.addr0()) return true;
316 if (s1.addr0() < s2.addr0() && s1.addr0() + s1.size() > s2.addr0())
317 return true;
318 if (s2.addr0() < s1.addr0() && s2.addr0() + s2.size() > s1.addr0())
319 return true;
320 return false;
321 }
322};
323
324struct ThreadSignalContext;
325
326struct JmpBuf {
327 uptr sp;
328 int int_signal_send;
329 bool in_blocking_func;
330 uptr in_signal_handler;
331 uptr *shadow_stack_pos;
332};
333
334// A Processor represents a physical thread, or a P for Go.
335// It is used to store internal resources like allocate cache, and does not
336// participate in race-detection logic (invisible to end user).
337// In C++ it is tied to an OS thread just like ThreadState, however ideally
338// it should be tied to a CPU (this way we will have fewer allocator caches).
339// In Go it is tied to a P, so there are significantly fewer Processor's than
340// ThreadState's (which are tied to Gs).
341// A ThreadState must be wired with a Processor to handle events.
342struct Processor {
343 ThreadState *thr; // currently wired thread, or nullptr
344#if !SANITIZER_GO
345 AllocatorCache alloc_cache;
346 InternalAllocatorCache internal_alloc_cache;
347#endif
348 DenseSlabAllocCache block_cache;
349 DenseSlabAllocCache sync_cache;
350 DenseSlabAllocCache clock_cache;
351 DDPhysicalThread *dd_pt;
352};
353
354#if !SANITIZER_GO
355// ScopedGlobalProcessor temporary setups a global processor for the current
356// thread, if it does not have one. Intended for interceptors that can run
357// at the very thread end, when we already destroyed the thread processor.
358struct ScopedGlobalProcessor {
359 ScopedGlobalProcessor();
360 ~ScopedGlobalProcessor();
361};
362#endif
363
364// This struct is stored in TLS.
365struct ThreadState {
366 FastState fast_state;
367 // Synch epoch represents the threads's epoch before the last synchronization
368 // action. It allows to reduce number of shadow state updates.
369 // For example, fast_synch_epoch=100, last write to addr X was at epoch=150,
370 // if we are processing write to X from the same thread at epoch=200,
371 // we do nothing, because both writes happen in the same 'synch epoch'.
372 // That is, if another memory access does not race with the former write,
373 // it does not race with the latter as well.
374 // QUESTION: can we can squeeze this into ThreadState::Fast?
375 // E.g. ThreadState::Fast is a 44-bit, 32 are taken by synch_epoch and 12 are
376 // taken by epoch between synchs.
377 // This way we can save one load from tls.
378 u64 fast_synch_epoch;
379 // Technically `current` should be a separate THREADLOCAL variable;
380 // but it is placed here in order to share cache line with previous fields.
381 ThreadState* current;
382 // This is a slow path flag. On fast path, fast_state.GetIgnoreBit() is read.
383 // We do not distinguish beteween ignoring reads and writes
384 // for better performance.
385 int ignore_reads_and_writes;
386 int ignore_sync;
387 int suppress_reports;
388 // Go does not support ignores.
389#if !SANITIZER_GO
390 IgnoreSet mop_ignore_set;
391 IgnoreSet sync_ignore_set;
392#endif
393 // C/C++ uses fixed size shadow stack embed into Trace.
394 // Go uses malloc-allocated shadow stack with dynamic size.
395 uptr *shadow_stack;
396 uptr *shadow_stack_end;
397 uptr *shadow_stack_pos;
398 u64 *racy_shadow_addr;
399 u64 racy_state[2];
400 MutexSet mset;
401 ThreadClock clock;
402#if !SANITIZER_GO
403 Vector<JmpBuf> jmp_bufs;
404 int ignore_interceptors;
405#endif
406#if TSAN_COLLECT_STATS
407 u64 stat[StatCnt];
408#endif
409 const int tid;
410 const int unique_id;
411 bool in_symbolizer;
412 bool in_ignored_lib;
413 bool is_inited;
414 bool is_dead;
415 bool is_freeing;
416 bool is_vptr_access;
417 const uptr stk_addr;
418 const uptr stk_size;
419 const uptr tls_addr;
420 const uptr tls_size;
421 ThreadContext *tctx;
422
423#if SANITIZER_DEBUG && !SANITIZER_GO
424 InternalDeadlockDetector internal_deadlock_detector;
425#endif
426 DDLogicalThread *dd_lt;
427
428 // Current wired Processor, or nullptr. Required to handle any events.
429 Processor *proc1;
430#if !SANITIZER_GO
431 Processor *proc() { return proc1; }
432#else
433 Processor *proc();
434#endif
435
436 atomic_uintptr_t in_signal_handler;
437 ThreadSignalContext *signal_ctx;
438
439#if !SANITIZER_GO
440 u32 last_sleep_stack_id;
441 ThreadClock last_sleep_clock;
442#endif
443
444 // Set in regions of runtime that must be signal-safe and fork-safe.
445 // If set, malloc must not be called.
446 int nomalloc;
447
448 const ReportDesc *current_report;
449
450 explicit ThreadState(Context *ctx, int tid, int unique_id, u64 epoch,
451 unsigned reuse_count,
452 uptr stk_addr, uptr stk_size,
453 uptr tls_addr, uptr tls_size);
454};
455
456#if !SANITIZER_GO
457#if SANITIZER_MAC || SANITIZER_ANDROID
458ThreadState *cur_thread();
459void set_cur_thread(ThreadState *thr);
460void cur_thread_finalize();
461INLINE void cur_thread_init() { }
462#else
463__attribute__((tls_model("initial-exec")))
464extern THREADLOCAL char cur_thread_placeholder[];
465INLINE ThreadState *cur_thread() {
466 return reinterpret_cast<ThreadState *>(cur_thread_placeholder)->current;
467}
468INLINE void cur_thread_init() {
469 ThreadState *thr = reinterpret_cast<ThreadState *>(cur_thread_placeholder);
470 if (UNLIKELY(!thr->current))
471 thr->current = thr;
472}
473INLINE void set_cur_thread(ThreadState *thr) {
474 reinterpret_cast<ThreadState *>(cur_thread_placeholder)->current = thr;
475}
476INLINE void cur_thread_finalize() { }
477#endif // SANITIZER_MAC || SANITIZER_ANDROID
478#endif // SANITIZER_GO
479
480class ThreadContext : public ThreadContextBase {
481 public:
482 explicit ThreadContext(int tid);
483 ~ThreadContext();
484 ThreadState *thr;
485 u32 creation_stack_id;
486 SyncClock sync;
487 // Epoch at which the thread had started.
488 // If we see an event from the thread stamped by an older epoch,
489 // the event is from a dead thread that shared tid with this thread.
490 u64 epoch0;
491 u64 epoch1;
492
493 // Override superclass callbacks.
494 void OnDead() override;
495 void OnJoined(void *arg) override;
496 void OnFinished() override;
497 void OnStarted(void *arg) override;
498 void OnCreated(void *arg) override;
499 void OnReset() override;
500 void OnDetached(void *arg) override;
501};
502
503struct RacyStacks {
504 MD5Hash hash[2];
505 bool operator==(const RacyStacks &other) const {
506 if (hash[0] == other.hash[0] && hash[1] == other.hash[1])
507 return true;
508 if (hash[0] == other.hash[1] && hash[1] == other.hash[0])
509 return true;
510 return false;
511 }
512};
513
514struct RacyAddress {
515 uptr addr_min;
516 uptr addr_max;
517};
518
519struct FiredSuppression {
520 ReportType type;
521 uptr pc_or_addr;
522 Suppression *supp;
523};
524
525struct Context {
526 Context();
527
528 bool initialized;
529#if !SANITIZER_GO
530 bool after_multithreaded_fork;
531#endif
532
533 MetaMap metamap;
534
535 Mutex report_mtx;
536 int nreported;
537 int nmissed_expected;
538 atomic_uint64_t last_symbolize_time_ns;
539
540 void *background_thread;
541 atomic_uint32_t stop_background_thread;
542
543 ThreadRegistry *thread_registry;
544
545 Mutex racy_mtx;
546 Vector<RacyStacks> racy_stacks;
547 Vector<RacyAddress> racy_addresses;
548 // Number of fired suppressions may be large enough.
549 Mutex fired_suppressions_mtx;
550 InternalMmapVector<FiredSuppression> fired_suppressions;
551 DDetector *dd;
552
553 ClockAlloc clock_alloc;
554
555 Flags flags;
556
557 u64 stat[StatCnt];
558 u64 int_alloc_cnt[MBlockTypeCount];
559 u64 int_alloc_siz[MBlockTypeCount];
560};
561
562extern Context *ctx; // The one and the only global runtime context.
563
564ALWAYS_INLINE Flags *flags() {
565 return &ctx->flags;
566}
567
568struct ScopedIgnoreInterceptors {
569 ScopedIgnoreInterceptors() {
570#if !SANITIZER_GO
571 cur_thread()->ignore_interceptors++;
572#endif
573 }
574
575 ~ScopedIgnoreInterceptors() {
576#if !SANITIZER_GO
577 cur_thread()->ignore_interceptors--;
578#endif
579 }
580};
581
582const char *GetObjectTypeFromTag(uptr tag);
583const char *GetReportHeaderFromTag(uptr tag);
584uptr TagFromShadowStackFrame(uptr pc);
585
586class ScopedReportBase {
587 public:
588 void AddMemoryAccess(uptr addr, uptr external_tag, Shadow s, StackTrace stack,
589 const MutexSet *mset);
590 void AddStack(StackTrace stack, bool suppressable = false);
591 void AddThread(const ThreadContext *tctx, bool suppressable = false);
592 void AddThread(int unique_tid, bool suppressable = false);
593 void AddUniqueTid(int unique_tid);
594 void AddMutex(const SyncVar *s);
595 u64 AddMutex(u64 id);
596 void AddLocation(uptr addr, uptr size);
597 void AddSleep(u32 stack_id);
598 void SetCount(int count);
599
600 const ReportDesc *GetReport() const;
601
602 protected:
603 ScopedReportBase(ReportType typ, uptr tag);
604 ~ScopedReportBase();
605
606 private:
607 ReportDesc *rep_;
608 // Symbolizer makes lots of intercepted calls. If we try to process them,
609 // at best it will cause deadlocks on internal mutexes.
610 ScopedIgnoreInterceptors ignore_interceptors_;
611
612 void AddDeadMutex(u64 id);
613
614 ScopedReportBase(const ScopedReportBase &) = delete;
615 void operator=(const ScopedReportBase &) = delete;
616};
617
618class ScopedReport : public ScopedReportBase {
619 public:
620 explicit ScopedReport(ReportType typ, uptr tag = kExternalTagNone);
621 ~ScopedReport();
622
623 private:
624 ScopedErrorReportLock lock_;
625};
626
627ThreadContext *IsThreadStackOrTls(uptr addr, bool *is_stack);
628void RestoreStack(int tid, const u64 epoch, VarSizeStackTrace *stk,
629 MutexSet *mset, uptr *tag = nullptr);
630
631// The stack could look like:
632// <start> | <main> | <foo> | tag | <bar>
633// This will extract the tag and keep:
634// <start> | <main> | <foo> | <bar>
635template<typename StackTraceTy>
636void ExtractTagFromStack(StackTraceTy *stack, uptr *tag = nullptr) {
637 if (stack->size < 2) return;
638 uptr possible_tag_pc = stack->trace[stack->size - 2];
639 uptr possible_tag = TagFromShadowStackFrame(possible_tag_pc);
640 if (possible_tag == kExternalTagNone) return;
641 stack->trace_buffer[stack->size - 2] = stack->trace_buffer[stack->size - 1];
642 stack->size -= 1;
643 if (tag) *tag = possible_tag;
644}
645
646template<typename StackTraceTy>
647void ObtainCurrentStack(ThreadState *thr, uptr toppc, StackTraceTy *stack,
648 uptr *tag = nullptr) {
649 uptr size = thr->shadow_stack_pos - thr->shadow_stack;
650 uptr start = 0;
651 if (size + !!toppc > kStackTraceMax) {
652 start = size + !!toppc - kStackTraceMax;
653 size = kStackTraceMax - !!toppc;
654 }
655 stack->Init(&thr->shadow_stack[start], size, toppc);
656 ExtractTagFromStack(stack, tag);
657}
658
659#define GET_STACK_TRACE_FATAL(thr, pc) \
660 VarSizeStackTrace stack; \
661 ObtainCurrentStack(thr, pc, &stack); \
662 stack.ReverseOrder();
663
664#if TSAN_COLLECT_STATS
665void StatAggregate(u64 *dst, u64 *src);
666void StatOutput(u64 *stat);
667#endif
668
669void ALWAYS_INLINE StatInc(ThreadState *thr, StatType typ, u64 n = 1) {
670#if TSAN_COLLECT_STATS
671 thr->stat[typ] += n;
672#endif
673}
674void ALWAYS_INLINE StatSet(ThreadState *thr, StatType typ, u64 n) {
675#if TSAN_COLLECT_STATS
676 thr->stat[typ] = n;
677#endif
678}
679
680void MapShadow(uptr addr, uptr size);
681void MapThreadTrace(uptr addr, uptr size, const char *name);
682void DontNeedShadowFor(uptr addr, uptr size);
683void UnmapShadow(ThreadState *thr, uptr addr, uptr size);
684void InitializeShadowMemory();
685void InitializeInterceptors();
686void InitializeLibIgnore();
687void InitializeDynamicAnnotations();
688
689void ForkBefore(ThreadState *thr, uptr pc);
690void ForkParentAfter(ThreadState *thr, uptr pc);
691void ForkChildAfter(ThreadState *thr, uptr pc);
692
693void ReportRace(ThreadState *thr);
694bool OutputReport(ThreadState *thr, const ScopedReport &srep);
695bool IsFiredSuppression(Context *ctx, ReportType type, StackTrace trace);
696bool IsExpectedReport(uptr addr, uptr size);
697void PrintMatchedBenignRaces();
698
699#if defined(TSAN_DEBUG_OUTPUT) && TSAN_DEBUG_OUTPUT >= 1
700# define DPrintf Printf
701#else
702# define DPrintf(...)
703#endif
704
705#if defined(TSAN_DEBUG_OUTPUT) && TSAN_DEBUG_OUTPUT >= 2
706# define DPrintf2 Printf
707#else
708# define DPrintf2(...)
709#endif
710
711u32 CurrentStackId(ThreadState *thr, uptr pc);
712ReportStack *SymbolizeStackId(u32 stack_id);
713void PrintCurrentStack(ThreadState *thr, uptr pc);
714void PrintCurrentStackSlow(uptr pc); // uses libunwind
715
716void Initialize(ThreadState *thr);
717void MaybeSpawnBackgroundThread();
718int Finalize(ThreadState *thr);
719
720void OnUserAlloc(ThreadState *thr, uptr pc, uptr p, uptr sz, bool write);
721void OnUserFree(ThreadState *thr, uptr pc, uptr p, bool write);
722
723void MemoryAccess(ThreadState *thr, uptr pc, uptr addr,
724 int kAccessSizeLog, bool kAccessIsWrite, bool kIsAtomic);
725void MemoryAccessImpl(ThreadState *thr, uptr addr,
726 int kAccessSizeLog, bool kAccessIsWrite, bool kIsAtomic,
727 u64 *shadow_mem, Shadow cur);
728void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr,
729 uptr size, bool is_write);
730void MemoryAccessRangeStep(ThreadState *thr, uptr pc, uptr addr,
731 uptr size, uptr step, bool is_write);
732void UnalignedMemoryAccess(ThreadState *thr, uptr pc, uptr addr,
733 int size, bool kAccessIsWrite, bool kIsAtomic);
734
735const int kSizeLog1 = 0;
736const int kSizeLog2 = 1;
737const int kSizeLog4 = 2;
738const int kSizeLog8 = 3;
739
740void ALWAYS_INLINE MemoryRead(ThreadState *thr, uptr pc,
741 uptr addr, int kAccessSizeLog) {
742 MemoryAccess(thr, pc, addr, kAccessSizeLog, false, false);
743}
744
745void ALWAYS_INLINE MemoryWrite(ThreadState *thr, uptr pc,
746 uptr addr, int kAccessSizeLog) {
747 MemoryAccess(thr, pc, addr, kAccessSizeLog, true, false);
748}
749
750void ALWAYS_INLINE MemoryReadAtomic(ThreadState *thr, uptr pc,
751 uptr addr, int kAccessSizeLog) {
752 MemoryAccess(thr, pc, addr, kAccessSizeLog, false, true);
753}
754
755void ALWAYS_INLINE MemoryWriteAtomic(ThreadState *thr, uptr pc,
756 uptr addr, int kAccessSizeLog) {
757 MemoryAccess(thr, pc, addr, kAccessSizeLog, true, true);
758}
759
760void MemoryResetRange(ThreadState *thr, uptr pc, uptr addr, uptr size);
761void MemoryRangeFreed(ThreadState *thr, uptr pc, uptr addr, uptr size);
762void MemoryRangeImitateWrite(ThreadState *thr, uptr pc, uptr addr, uptr size);
763void MemoryRangeImitateWriteOrResetRange(ThreadState *thr, uptr pc, uptr addr,
764 uptr size);
765
766void ThreadIgnoreBegin(ThreadState *thr, uptr pc, bool save_stack = true);
767void ThreadIgnoreEnd(ThreadState *thr, uptr pc);
768void ThreadIgnoreSyncBegin(ThreadState *thr, uptr pc, bool save_stack = true);
769void ThreadIgnoreSyncEnd(ThreadState *thr, uptr pc);
770
771void FuncEntry(ThreadState *thr, uptr pc);
772void FuncExit(ThreadState *thr);
773
774int ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached);
775void ThreadStart(ThreadState *thr, int tid, tid_t os_id,
776 ThreadType thread_type);
777void ThreadFinish(ThreadState *thr);
778int ThreadConsumeTid(ThreadState *thr, uptr pc, uptr uid);
779void ThreadJoin(ThreadState *thr, uptr pc, int tid);
780void ThreadDetach(ThreadState *thr, uptr pc, int tid);
781void ThreadFinalize(ThreadState *thr);
782void ThreadSetName(ThreadState *thr, const char *name);
783int ThreadCount(ThreadState *thr);
784void ProcessPendingSignals(ThreadState *thr);
785void ThreadNotJoined(ThreadState *thr, uptr pc, int tid, uptr uid);
786
787Processor *ProcCreate();
788void ProcDestroy(Processor *proc);
789void ProcWire(Processor *proc, ThreadState *thr);
790void ProcUnwire(Processor *proc, ThreadState *thr);
791
792// Note: the parameter is called flagz, because flags is already taken
793// by the global function that returns flags.
794void MutexCreate(ThreadState *thr, uptr pc, uptr addr, u32 flagz = 0);
795void MutexDestroy(ThreadState *thr, uptr pc, uptr addr, u32 flagz = 0);
796void MutexPreLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz = 0);
797void MutexPostLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz = 0,
798 int rec = 1);
799int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, u32 flagz = 0);
800void MutexPreReadLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz = 0);
801void MutexPostReadLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz = 0);
802void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr);
803void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr);
804void MutexRepair(ThreadState *thr, uptr pc, uptr addr); // call on EOWNERDEAD
805void MutexInvalidAccess(ThreadState *thr, uptr pc, uptr addr);
806
807void Acquire(ThreadState *thr, uptr pc, uptr addr);
808// AcquireGlobal synchronizes the current thread with all other threads.
809// In terms of happens-before relation, it draws a HB edge from all threads
810// (where they happen to execute right now) to the current thread. We use it to
811// handle Go finalizers. Namely, finalizer goroutine executes AcquireGlobal
812// right before executing finalizers. This provides a coarse, but simple
813// approximation of the actual required synchronization.
814void AcquireGlobal(ThreadState *thr, uptr pc);
815void Release(ThreadState *thr, uptr pc, uptr addr);
816void ReleaseStoreAcquire(ThreadState *thr, uptr pc, uptr addr);
817void ReleaseStore(ThreadState *thr, uptr pc, uptr addr);
818void AfterSleep(ThreadState *thr, uptr pc);
819void AcquireImpl(ThreadState *thr, uptr pc, SyncClock *c);
820void ReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c);
821void ReleaseStoreAcquireImpl(ThreadState *thr, uptr pc, SyncClock *c);
822void ReleaseStoreImpl(ThreadState *thr, uptr pc, SyncClock *c);
823void AcquireReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c);
824
825// The hacky call uses custom calling convention and an assembly thunk.
826// It is considerably faster that a normal call for the caller
827// if it is not executed (it is intended for slow paths from hot functions).
828// The trick is that the call preserves all registers and the compiler
829// does not treat it as a call.
830// If it does not work for you, use normal call.
831#if !SANITIZER_DEBUG && defined(__x86_64__) && !SANITIZER_MAC
832// The caller may not create the stack frame for itself at all,
833// so we create a reserve stack frame for it (1024b must be enough).
834#define HACKY_CALL(f) \
835 __asm__ __volatile__("sub $1024, %%rsp;" \
836 CFI_INL_ADJUST_CFA_OFFSET(1024) \
837 ".hidden " #f "_thunk;" \
838 "call " #f "_thunk;" \
839 "add $1024, %%rsp;" \
840 CFI_INL_ADJUST_CFA_OFFSET(-1024) \
841 ::: "memory", "cc");
842#else
843#define HACKY_CALL(f) f()
844#endif
845
846void TraceSwitch(ThreadState *thr);
847uptr TraceTopPC(ThreadState *thr);
848uptr TraceSize();
849uptr TraceParts();
850Trace *ThreadTrace(int tid);
851
852extern "C" void __tsan_trace_switch();
853void ALWAYS_INLINE TraceAddEvent(ThreadState *thr, FastState fs,
854 EventType typ, u64 addr) {
855 if (!kCollectHistory)
856 return;
857 DCHECK_GE((int)typ, 0);
858 DCHECK_LE((int)typ, 7);
859 DCHECK_EQ(GetLsb(addr, kEventPCBits), addr);
860 StatInc(thr, StatEvents);
861 u64 pos = fs.GetTracePos();
862 if (UNLIKELY((pos % kTracePartSize) == 0)) {
863#if !SANITIZER_GO
864 HACKY_CALL(__tsan_trace_switch);
865#else
866 TraceSwitch(thr);
867#endif
868 }
869 Event *trace = (Event*)GetThreadTrace(fs.tid());
870 Event *evp = &trace[pos];
871 Event ev = (u64)addr | ((u64)typ << kEventPCBits);
872 *evp = ev;
873}
874
875#if !SANITIZER_GO
876uptr ALWAYS_INLINE HeapEnd() {
877 return HeapMemEnd() + PrimaryAllocator::AdditionalSize();
878}
879#endif
880
881ThreadState *FiberCreate(ThreadState *thr, uptr pc, unsigned flags);
882void FiberDestroy(ThreadState *thr, uptr pc, ThreadState *fiber);
883void FiberSwitch(ThreadState *thr, uptr pc, ThreadState *fiber, unsigned flags);
884
885// These need to match __tsan_switch_to_fiber_* flags defined in
886// tsan_interface.h. See documentation there as well.
887enum FiberSwitchFlags {
888 FiberSwitchFlagNoSync = 1 << 0, // __tsan_switch_to_fiber_no_sync
889};
890
891} // namespace __tsan
892
893#endif // TSAN_RTL_H
lib/tsan/tsan_rtl_mutex.cpp created+562
...@@ -0,0 +1,562 @@
1//===-- tsan_rtl_mutex.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#include <sanitizer_common/sanitizer_deadlock_detector_interface.h>
14#include <sanitizer_common/sanitizer_stackdepot.h>
15
16#include "tsan_rtl.h"
17#include "tsan_flags.h"
18#include "tsan_sync.h"
19#include "tsan_report.h"
20#include "tsan_symbolize.h"
21#include "tsan_platform.h"
22
23namespace __tsan {
24
25void ReportDeadlock(ThreadState *thr, uptr pc, DDReport *r);
26
27struct Callback : DDCallback {
28 ThreadState *thr;
29 uptr pc;
30
31 Callback(ThreadState *thr, uptr pc)
32 : thr(thr)
33 , pc(pc) {
34 DDCallback::pt = thr->proc()->dd_pt;
35 DDCallback::lt = thr->dd_lt;
36 }
37
38 u32 Unwind() override { return CurrentStackId(thr, pc); }
39 int UniqueTid() override { return thr->unique_id; }
40};
41
42void DDMutexInit(ThreadState *thr, uptr pc, SyncVar *s) {
43 Callback cb(thr, pc);
44 ctx->dd->MutexInit(&cb, &s->dd);
45 s->dd.ctx = s->GetId();
46}
47
48static void ReportMutexMisuse(ThreadState *thr, uptr pc, ReportType typ,
49 uptr addr, u64 mid) {
50 // In Go, these misuses are either impossible, or detected by std lib,
51 // or false positives (e.g. unlock in a different thread).
52 if (SANITIZER_GO)
53 return;
54 ThreadRegistryLock l(ctx->thread_registry);
55 ScopedReport rep(typ);
56 rep.AddMutex(mid);
57 VarSizeStackTrace trace;
58 ObtainCurrentStack(thr, pc, &trace);
59 rep.AddStack(trace, true);
60 rep.AddLocation(addr, 1);
61 OutputReport(thr, rep);
62}
63
64void MutexCreate(ThreadState *thr, uptr pc, uptr addr, u32 flagz) {
65 DPrintf("#%d: MutexCreate %zx flagz=0x%x\n", thr->tid, addr, flagz);
66 StatInc(thr, StatMutexCreate);
67 if (!(flagz & MutexFlagLinkerInit) && IsAppMem(addr)) {
68 CHECK(!thr->is_freeing);
69 thr->is_freeing = true;
70 MemoryWrite(thr, pc, addr, kSizeLog1);
71 thr->is_freeing = false;
72 }
73 SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true);
74 s->SetFlags(flagz & MutexCreationFlagMask);
75 if (!SANITIZER_GO && s->creation_stack_id == 0)
76 s->creation_stack_id = CurrentStackId(thr, pc);
77 s->mtx.Unlock();
78}
79
80void MutexDestroy(ThreadState *thr, uptr pc, uptr addr, u32 flagz) {
81 DPrintf("#%d: MutexDestroy %zx\n", thr->tid, addr);
82 StatInc(thr, StatMutexDestroy);
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 }
98 bool unlock_locked = false;
99 if (flags()->report_destroy_locked
100 && s->owner_tid != SyncVar::kInvalidTid
101 && !s->IsFlagSet(MutexFlagBroken)) {
102 s->SetFlags(MutexFlagBroken);
103 unlock_locked = true;
104 }
105 u64 mid = s->GetId();
106 u64 last_lock = s->last_lock;
107 if (!unlock_locked)
108 s->Reset(thr->proc()); // must not reset it before the report is printed
109 s->mtx.Unlock();
110 if (unlock_locked) {
111 ThreadRegistryLock l(ctx->thread_registry);
112 ScopedReport rep(ReportTypeMutexDestroyLocked);
113 rep.AddMutex(mid);
114 VarSizeStackTrace trace;
115 ObtainCurrentStack(thr, pc, &trace);
116 rep.AddStack(trace, true);
117 FastState last(last_lock);
118 RestoreStack(last.tid(), last.epoch(), &trace, 0);
119 rep.AddStack(trace, true);
120 rep.AddLocation(addr, 1);
121 OutputReport(thr, rep);
122
123 SyncVar *s = ctx->metamap.GetIfExistsAndLock(addr, true);
124 if (s != 0) {
125 s->Reset(thr->proc());
126 s->mtx.Unlock();
127 }
128 }
129 thr->mset.Remove(mid);
130 // Imitate a memory write to catch unlock-destroy races.
131 // Do this outside of sync mutex, because it can report a race which locks
132 // sync mutexes.
133 if (IsAppMem(addr)) {
134 CHECK(!thr->is_freeing);
135 thr->is_freeing = true;
136 MemoryWrite(thr, pc, addr, kSizeLog1);
137 thr->is_freeing = false;
138 }
139 // s will be destroyed and freed in MetaMap::FreeBlock.
140}
141
142void MutexPreLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) {
143 DPrintf("#%d: MutexPreLock %zx flagz=0x%x\n", thr->tid, addr, flagz);
144 if (!(flagz & MutexFlagTryLock) && common_flags()->detect_deadlocks) {
145 SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, false);
146 s->UpdateFlags(flagz);
147 if (s->owner_tid != thr->tid) {
148 Callback cb(thr, pc);
149 ctx->dd->MutexBeforeLock(&cb, &s->dd, true);
150 s->mtx.ReadUnlock();
151 ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
152 } else {
153 s->mtx.ReadUnlock();
154 }
155 }
156}
157
158void MutexPostLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz, int rec) {
159 DPrintf("#%d: MutexPostLock %zx flag=0x%x rec=%d\n",
160 thr->tid, addr, flagz, rec);
161 if (flagz & MutexFlagRecursiveLock)
162 CHECK_GT(rec, 0);
163 else
164 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());
171 bool report_double_lock = false;
172 if (s->owner_tid == SyncVar::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 StatInc(thr, StatMutexLock);
186 AcquireImpl(thr, pc, &s->clock);
187 AcquireImpl(thr, pc, &s->read_clock);
188 } else if (!s->IsFlagSet(MutexFlagWriteReentrant)) {
189 StatInc(thr, StatMutexRecLock);
190 }
191 thr->mset.Add(s->GetId(), true, thr->fast_state.epoch());
192 bool pre_lock = false;
193 if (first && common_flags()->detect_deadlocks) {
194 pre_lock = (flagz & MutexFlagDoPreLockOnPostLock) &&
195 !(flagz & MutexFlagTryLock);
196 Callback cb(thr, pc);
197 if (pre_lock)
198 ctx->dd->MutexBeforeLock(&cb, &s->dd, true);
199 ctx->dd->MutexAfterLock(&cb, &s->dd, true, flagz & MutexFlagTryLock);
200 }
201 u64 mid = s->GetId();
202 s->mtx.Unlock();
203 // Can't touch s after this point.
204 s = 0;
205 if (report_double_lock)
206 ReportMutexMisuse(thr, pc, ReportTypeMutexDoubleLock, addr, mid);
207 if (first && pre_lock && common_flags()->detect_deadlocks) {
208 Callback cb(thr, pc);
209 ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
210 }
211}
212
213int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) {
214 DPrintf("#%d: MutexUnlock %zx flagz=0x%x\n", thr->tid, addr, flagz);
215 if (IsAppMem(addr))
216 MemoryReadAtomic(thr, pc, addr, kSizeLog1);
217 SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true);
218 thr->fast_state.IncrementEpoch();
219 TraceAddEvent(thr, thr->fast_state, EventTypeUnlock, s->GetId());
220 int rec = 0;
221 bool report_bad_unlock = false;
222 if (!SANITIZER_GO && (s->recursion == 0 || s->owner_tid != thr->tid)) {
223 if (flags()->report_mutex_bugs && !s->IsFlagSet(MutexFlagBroken)) {
224 s->SetFlags(MutexFlagBroken);
225 report_bad_unlock = true;
226 }
227 } else {
228 rec = (flagz & MutexFlagRecursiveUnlock) ? s->recursion : 1;
229 s->recursion -= rec;
230 if (s->recursion == 0) {
231 StatInc(thr, StatMutexUnlock);
232 s->owner_tid = SyncVar::kInvalidTid;
233 ReleaseStoreImpl(thr, pc, &s->clock);
234 } else {
235 StatInc(thr, StatMutexRecUnlock);
236 }
237 }
238 thr->mset.Del(s->GetId(), true);
239 if (common_flags()->detect_deadlocks && s->recursion == 0 &&
240 !report_bad_unlock) {
241 Callback cb(thr, pc);
242 ctx->dd->MutexBeforeUnlock(&cb, &s->dd, true);
243 }
244 u64 mid = s->GetId();
245 s->mtx.Unlock();
246 // Can't touch s after this point.
247 if (report_bad_unlock)
248 ReportMutexMisuse(thr, pc, ReportTypeMutexBadUnlock, addr, mid);
249 if (common_flags()->detect_deadlocks && !report_bad_unlock) {
250 Callback cb(thr, pc);
251 ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
252 }
253 return rec;
254}
255
256void MutexPreReadLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) {
257 DPrintf("#%d: MutexPreReadLock %zx flagz=0x%x\n", thr->tid, addr, flagz);
258 if (!(flagz & MutexFlagTryLock) && common_flags()->detect_deadlocks) {
259 SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, false);
260 s->UpdateFlags(flagz);
261 Callback cb(thr, pc);
262 ctx->dd->MutexBeforeLock(&cb, &s->dd, false);
263 s->mtx.ReadUnlock();
264 ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
265 }
266}
267
268void MutexPostReadLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) {
269 DPrintf("#%d: MutexPostReadLock %zx flagz=0x%x\n", thr->tid, addr, flagz);
270 StatInc(thr, StatMutexReadLock);
271 if (IsAppMem(addr))
272 MemoryReadAtomic(thr, pc, addr, kSizeLog1);
273 SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, false);
274 s->UpdateFlags(flagz);
275 thr->fast_state.IncrementEpoch();
276 TraceAddEvent(thr, thr->fast_state, EventTypeRLock, s->GetId());
277 bool report_bad_lock = false;
278 if (s->owner_tid != SyncVar::kInvalidTid) {
279 if (flags()->report_mutex_bugs && !s->IsFlagSet(MutexFlagBroken)) {
280 s->SetFlags(MutexFlagBroken);
281 report_bad_lock = true;
282 }
283 }
284 AcquireImpl(thr, pc, &s->clock);
285 s->last_lock = thr->fast_state.raw();
286 thr->mset.Add(s->GetId(), false, thr->fast_state.epoch());
287 bool pre_lock = false;
288 if (common_flags()->detect_deadlocks) {
289 pre_lock = (flagz & MutexFlagDoPreLockOnPostLock) &&
290 !(flagz & MutexFlagTryLock);
291 Callback cb(thr, pc);
292 if (pre_lock)
293 ctx->dd->MutexBeforeLock(&cb, &s->dd, false);
294 ctx->dd->MutexAfterLock(&cb, &s->dd, false, flagz & MutexFlagTryLock);
295 }
296 u64 mid = s->GetId();
297 s->mtx.ReadUnlock();
298 // Can't touch s after this point.
299 s = 0;
300 if (report_bad_lock)
301 ReportMutexMisuse(thr, pc, ReportTypeMutexBadReadLock, addr, mid);
302 if (pre_lock && common_flags()->detect_deadlocks) {
303 Callback cb(thr, pc);
304 ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
305 }
306}
307
308void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr) {
309 DPrintf("#%d: MutexReadUnlock %zx\n", thr->tid, addr);
310 StatInc(thr, StatMutexReadUnlock);
311 if (IsAppMem(addr))
312 MemoryReadAtomic(thr, pc, addr, kSizeLog1);
313 SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true);
314 thr->fast_state.IncrementEpoch();
315 TraceAddEvent(thr, thr->fast_state, EventTypeRUnlock, s->GetId());
316 bool report_bad_unlock = false;
317 if (s->owner_tid != SyncVar::kInvalidTid) {
318 if (flags()->report_mutex_bugs && !s->IsFlagSet(MutexFlagBroken)) {
319 s->SetFlags(MutexFlagBroken);
320 report_bad_unlock = true;
321 }
322 }
323 ReleaseImpl(thr, pc, &s->read_clock);
324 if (common_flags()->detect_deadlocks && s->recursion == 0) {
325 Callback cb(thr, pc);
326 ctx->dd->MutexBeforeUnlock(&cb, &s->dd, false);
327 }
328 u64 mid = s->GetId();
329 s->mtx.Unlock();
330 // Can't touch s after this point.
331 thr->mset.Del(mid, false);
332 if (report_bad_unlock)
333 ReportMutexMisuse(thr, pc, ReportTypeMutexBadReadUnlock, addr, mid);
334 if (common_flags()->detect_deadlocks) {
335 Callback cb(thr, pc);
336 ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
337 }
338}
339
340void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr) {
341 DPrintf("#%d: MutexReadOrWriteUnlock %zx\n", thr->tid, addr);
342 if (IsAppMem(addr))
343 MemoryReadAtomic(thr, pc, addr, kSizeLog1);
344 SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true);
345 bool write = true;
346 bool report_bad_unlock = false;
347 if (s->owner_tid == SyncVar::kInvalidTid) {
348 // Seems to be read unlock.
349 write = false;
350 StatInc(thr, StatMutexReadUnlock);
351 thr->fast_state.IncrementEpoch();
352 TraceAddEvent(thr, thr->fast_state, EventTypeRUnlock, s->GetId());
353 ReleaseImpl(thr, pc, &s->read_clock);
354 } else if (s->owner_tid == thr->tid) {
355 // Seems to be write unlock.
356 thr->fast_state.IncrementEpoch();
357 TraceAddEvent(thr, thr->fast_state, EventTypeUnlock, s->GetId());
358 CHECK_GT(s->recursion, 0);
359 s->recursion--;
360 if (s->recursion == 0) {
361 StatInc(thr, StatMutexUnlock);
362 s->owner_tid = SyncVar::kInvalidTid;
363 ReleaseStoreImpl(thr, pc, &s->clock);
364 } else {
365 StatInc(thr, StatMutexRecUnlock);
366 }
367 } else if (!s->IsFlagSet(MutexFlagBroken)) {
368 s->SetFlags(MutexFlagBroken);
369 report_bad_unlock = true;
370 }
371 thr->mset.Del(s->GetId(), write);
372 if (common_flags()->detect_deadlocks && s->recursion == 0) {
373 Callback cb(thr, pc);
374 ctx->dd->MutexBeforeUnlock(&cb, &s->dd, write);
375 }
376 u64 mid = s->GetId();
377 s->mtx.Unlock();
378 // Can't touch s after this point.
379 if (report_bad_unlock)
380 ReportMutexMisuse(thr, pc, ReportTypeMutexBadUnlock, addr, mid);
381 if (common_flags()->detect_deadlocks) {
382 Callback cb(thr, pc);
383 ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
384 }
385}
386
387void MutexRepair(ThreadState *thr, uptr pc, uptr addr) {
388 DPrintf("#%d: MutexRepair %zx\n", thr->tid, addr);
389 SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true);
390 s->owner_tid = SyncVar::kInvalidTid;
391 s->recursion = 0;
392 s->mtx.Unlock();
393}
394
395void MutexInvalidAccess(ThreadState *thr, uptr pc, uptr addr) {
396 DPrintf("#%d: MutexInvalidAccess %zx\n", thr->tid, addr);
397 SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true);
398 u64 mid = s->GetId();
399 s->mtx.Unlock();
400 ReportMutexMisuse(thr, pc, ReportTypeMutexInvalidAccess, addr, mid);
401}
402
403void Acquire(ThreadState *thr, uptr pc, uptr addr) {
404 DPrintf("#%d: Acquire %zx\n", thr->tid, addr);
405 if (thr->ignore_sync)
406 return;
407 SyncVar *s = ctx->metamap.GetIfExistsAndLock(addr, false);
408 if (!s)
409 return;
410 AcquireImpl(thr, pc, &s->clock);
411 s->mtx.ReadUnlock();
412}
413
414static void UpdateClockCallback(ThreadContextBase *tctx_base, void *arg) {
415 ThreadState *thr = reinterpret_cast<ThreadState*>(arg);
416 ThreadContext *tctx = static_cast<ThreadContext*>(tctx_base);
417 u64 epoch = tctx->epoch1;
418 if (tctx->status == ThreadStatusRunning) {
419 epoch = tctx->thr->fast_state.epoch();
420 tctx->thr->clock.NoteGlobalAcquire(epoch);
421 }
422 thr->clock.set(&thr->proc()->clock_cache, tctx->tid, epoch);
423}
424
425void AcquireGlobal(ThreadState *thr, uptr pc) {
426 DPrintf("#%d: AcquireGlobal\n", thr->tid);
427 if (thr->ignore_sync)
428 return;
429 ThreadRegistryLock l(ctx->thread_registry);
430 ctx->thread_registry->RunCallbackForEachThreadLocked(
431 UpdateClockCallback, thr);
432}
433
434void ReleaseStoreAcquire(ThreadState *thr, uptr pc, uptr addr) {
435 DPrintf("#%d: ReleaseStoreAcquire %zx\n", thr->tid, addr);
436 if (thr->ignore_sync)
437 return;
438 SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true);
439 thr->fast_state.IncrementEpoch();
440 // Can't increment epoch w/o writing to the trace as well.
441 TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
442 ReleaseStoreAcquireImpl(thr, pc, &s->clock);
443 s->mtx.Unlock();
444}
445
446void Release(ThreadState *thr, uptr pc, uptr addr) {
447 DPrintf("#%d: Release %zx\n", thr->tid, addr);
448 if (thr->ignore_sync)
449 return;
450 SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true);
451 thr->fast_state.IncrementEpoch();
452 // Can't increment epoch w/o writing to the trace as well.
453 TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
454 ReleaseImpl(thr, pc, &s->clock);
455 s->mtx.Unlock();
456}
457
458void ReleaseStore(ThreadState *thr, uptr pc, uptr addr) {
459 DPrintf("#%d: ReleaseStore %zx\n", thr->tid, addr);
460 if (thr->ignore_sync)
461 return;
462 SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true);
463 thr->fast_state.IncrementEpoch();
464 // Can't increment epoch w/o writing to the trace as well.
465 TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
466 ReleaseStoreImpl(thr, pc, &s->clock);
467 s->mtx.Unlock();
468}
469
470#if !SANITIZER_GO
471static void UpdateSleepClockCallback(ThreadContextBase *tctx_base, void *arg) {
472 ThreadState *thr = reinterpret_cast<ThreadState*>(arg);
473 ThreadContext *tctx = static_cast<ThreadContext*>(tctx_base);
474 u64 epoch = tctx->epoch1;
475 if (tctx->status == ThreadStatusRunning)
476 epoch = tctx->thr->fast_state.epoch();
477 thr->last_sleep_clock.set(&thr->proc()->clock_cache, tctx->tid, epoch);
478}
479
480void AfterSleep(ThreadState *thr, uptr pc) {
481 DPrintf("#%d: AfterSleep %zx\n", thr->tid);
482 if (thr->ignore_sync)
483 return;
484 thr->last_sleep_stack_id = CurrentStackId(thr, pc);
485 ThreadRegistryLock l(ctx->thread_registry);
486 ctx->thread_registry->RunCallbackForEachThreadLocked(
487 UpdateSleepClockCallback, thr);
488}
489#endif
490
491void AcquireImpl(ThreadState *thr, uptr pc, SyncClock *c) {
492 if (thr->ignore_sync)
493 return;
494 thr->clock.set(thr->fast_state.epoch());
495 thr->clock.acquire(&thr->proc()->clock_cache, c);
496 StatInc(thr, StatSyncAcquire);
497}
498
499void ReleaseStoreAcquireImpl(ThreadState *thr, uptr pc, SyncClock *c) {
500 if (thr->ignore_sync)
501 return;
502 thr->clock.set(thr->fast_state.epoch());
503 thr->fast_synch_epoch = thr->fast_state.epoch();
504 thr->clock.releaseStoreAcquire(&thr->proc()->clock_cache, c);
505 StatInc(thr, StatSyncReleaseStoreAcquire);
506}
507
508void ReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c) {
509 if (thr->ignore_sync)
510 return;
511 thr->clock.set(thr->fast_state.epoch());
512 thr->fast_synch_epoch = thr->fast_state.epoch();
513 thr->clock.release(&thr->proc()->clock_cache, c);
514 StatInc(thr, StatSyncRelease);
515}
516
517void ReleaseStoreImpl(ThreadState *thr, uptr pc, SyncClock *c) {
518 if (thr->ignore_sync)
519 return;
520 thr->clock.set(thr->fast_state.epoch());
521 thr->fast_synch_epoch = thr->fast_state.epoch();
522 thr->clock.ReleaseStore(&thr->proc()->clock_cache, c);
523 StatInc(thr, StatSyncRelease);
524}
525
526void AcquireReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c) {
527 if (thr->ignore_sync)
528 return;
529 thr->clock.set(thr->fast_state.epoch());
530 thr->fast_synch_epoch = thr->fast_state.epoch();
531 thr->clock.acq_rel(&thr->proc()->clock_cache, c);
532 StatInc(thr, StatSyncAcquire);
533 StatInc(thr, StatSyncRelease);
534}
535
536void ReportDeadlock(ThreadState *thr, uptr pc, DDReport *r) {
537 if (r == 0)
538 return;
539 ThreadRegistryLock l(ctx->thread_registry);
540 ScopedReport rep(ReportTypeDeadlock);
541 for (int i = 0; i < r->n; i++) {
542 rep.AddMutex(r->loop[i].mtx_ctx0);
543 rep.AddUniqueTid((int)r->loop[i].thr_ctx);
544 rep.AddThread((int)r->loop[i].thr_ctx);
545 }
546 uptr dummy_pc = 0x42;
547 for (int i = 0; i < r->n; i++) {
548 for (int j = 0; j < (flags()->second_deadlock_stack ? 2 : 1); j++) {
549 u32 stk = r->loop[i].stk[j];
550 if (stk && stk != 0xffffffff) {
551 rep.AddStack(StackDepotGet(stk), true);
552 } else {
553 // Sometimes we fail to extract the stack trace (FIXME: investigate),
554 // but we should still produce some stack trace in the report.
555 rep.AddStack(StackTrace(&dummy_pc, 1), true);
556 }
557 }
558 }
559 OutputReport(thr, rep);
560}
561
562} // namespace __tsan
lib/tsan/tsan_rtl_proc.cpp created+60
...@@ -0,0 +1,60 @@
1//===-- tsan_rtl_proc.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#include "sanitizer_common/sanitizer_placement_new.h"
14#include "tsan_rtl.h"
15#include "tsan_mman.h"
16#include "tsan_flags.h"
17
18namespace __tsan {
19
20Processor *ProcCreate() {
21 void *mem = InternalAlloc(sizeof(Processor));
22 internal_memset(mem, 0, sizeof(Processor));
23 Processor *proc = new(mem) Processor;
24 proc->thr = nullptr;
25#if !SANITIZER_GO
26 AllocatorProcStart(proc);
27#endif
28 if (common_flags()->detect_deadlocks)
29 proc->dd_pt = ctx->dd->CreatePhysicalThread();
30 return proc;
31}
32
33void ProcDestroy(Processor *proc) {
34 CHECK_EQ(proc->thr, nullptr);
35#if !SANITIZER_GO
36 AllocatorProcFinish(proc);
37#endif
38 ctx->clock_alloc.FlushCache(&proc->clock_cache);
39 ctx->metamap.OnProcIdle(proc);
40 if (common_flags()->detect_deadlocks)
41 ctx->dd->DestroyPhysicalThread(proc->dd_pt);
42 proc->~Processor();
43 InternalFree(proc);
44}
45
46void ProcWire(Processor *proc, ThreadState *thr) {
47 CHECK_EQ(thr->proc1, nullptr);
48 CHECK_EQ(proc->thr, nullptr);
49 thr->proc1 = proc;
50 proc->thr = thr;
51}
52
53void ProcUnwire(Processor *proc, ThreadState *thr) {
54 CHECK_EQ(thr->proc1, proc);
55 CHECK_EQ(proc->thr, thr);
56 thr->proc1 = nullptr;
57 proc->thr = nullptr;
58}
59
60} // namespace __tsan
lib/tsan/tsan_rtl_report.cpp created+754
...@@ -0,0 +1,754 @@
1//===-- tsan_rtl_report.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#include "sanitizer_common/sanitizer_libc.h"
14#include "sanitizer_common/sanitizer_placement_new.h"
15#include "sanitizer_common/sanitizer_stackdepot.h"
16#include "sanitizer_common/sanitizer_common.h"
17#include "sanitizer_common/sanitizer_stacktrace.h"
18#include "tsan_platform.h"
19#include "tsan_rtl.h"
20#include "tsan_suppressions.h"
21#include "tsan_symbolize.h"
22#include "tsan_report.h"
23#include "tsan_sync.h"
24#include "tsan_mman.h"
25#include "tsan_flags.h"
26#include "tsan_fd.h"
27
28namespace __tsan {
29
30using namespace __sanitizer;
31
32static ReportStack *SymbolizeStack(StackTrace trace);
33
34void TsanCheckFailed(const char *file, int line, const char *cond,
35 u64 v1, u64 v2) {
36 // There is high probability that interceptors will check-fail as well,
37 // on the other hand there is no sense in processing interceptors
38 // since we are going to die soon.
39 ScopedIgnoreInterceptors ignore;
40#if !SANITIZER_GO
41 cur_thread()->ignore_sync++;
42 cur_thread()->ignore_reads_and_writes++;
43#endif
44 Printf("FATAL: ThreadSanitizer CHECK failed: "
45 "%s:%d \"%s\" (0x%zx, 0x%zx)\n",
46 file, line, cond, (uptr)v1, (uptr)v2);
47 PrintCurrentStackSlow(StackTrace::GetCurrentPc());
48 Die();
49}
50
51// Can be overriden by an application/test to intercept reports.
52#ifdef TSAN_EXTERNAL_HOOKS
53bool OnReport(const ReportDesc *rep, bool suppressed);
54#else
55SANITIZER_WEAK_CXX_DEFAULT_IMPL
56bool OnReport(const ReportDesc *rep, bool suppressed) {
57 (void)rep;
58 return suppressed;
59}
60#endif
61
62SANITIZER_WEAK_DEFAULT_IMPL
63void __tsan_on_report(const ReportDesc *rep) {
64 (void)rep;
65}
66
67static void StackStripMain(SymbolizedStack *frames) {
68 SymbolizedStack *last_frame = nullptr;
69 SymbolizedStack *last_frame2 = nullptr;
70 for (SymbolizedStack *cur = frames; cur; cur = cur->next) {
71 last_frame2 = last_frame;
72 last_frame = cur;
73 }
74
75 if (last_frame2 == 0)
76 return;
77#if !SANITIZER_GO
78 const char *last = last_frame->info.function;
79 const char *last2 = last_frame2->info.function;
80 // Strip frame above 'main'
81 if (last2 && 0 == internal_strcmp(last2, "main")) {
82 last_frame->ClearAll();
83 last_frame2->next = nullptr;
84 // Strip our internal thread start routine.
85 } else if (last && 0 == internal_strcmp(last, "__tsan_thread_start_func")) {
86 last_frame->ClearAll();
87 last_frame2->next = nullptr;
88 // Strip global ctors init.
89 } else if (last && 0 == internal_strcmp(last, "__do_global_ctors_aux")) {
90 last_frame->ClearAll();
91 last_frame2->next = nullptr;
92 // If both are 0, then we probably just failed to symbolize.
93 } else if (last || last2) {
94 // Ensure that we recovered stack completely. Trimmed stack
95 // can actually happen if we do not instrument some code,
96 // so it's only a debug print. However we must try hard to not miss it
97 // due to our fault.
98 DPrintf("Bottom stack frame is missed\n");
99 }
100#else
101 // The last frame always point into runtime (gosched0, goexit0, runtime.main).
102 last_frame->ClearAll();
103 last_frame2->next = nullptr;
104#endif
105}
106
107ReportStack *SymbolizeStackId(u32 stack_id) {
108 if (stack_id == 0)
109 return 0;
110 StackTrace stack = StackDepotGet(stack_id);
111 if (stack.trace == nullptr)
112 return nullptr;
113 return SymbolizeStack(stack);
114}
115
116static ReportStack *SymbolizeStack(StackTrace trace) {
117 if (trace.size == 0)
118 return 0;
119 SymbolizedStack *top = nullptr;
120 for (uptr si = 0; si < trace.size; si++) {
121 const uptr pc = trace.trace[si];
122 uptr pc1 = pc;
123 // We obtain the return address, but we're interested in the previous
124 // instruction.
125 if ((pc & kExternalPCBit) == 0)
126 pc1 = StackTrace::GetPreviousInstructionPc(pc);
127 SymbolizedStack *ent = SymbolizeCode(pc1);
128 CHECK_NE(ent, 0);
129 SymbolizedStack *last = ent;
130 while (last->next) {
131 last->info.address = pc; // restore original pc for report
132 last = last->next;
133 }
134 last->info.address = pc; // restore original pc for report
135 last->next = top;
136 top = ent;
137 }
138 StackStripMain(top);
139
140 ReportStack *stack = ReportStack::New();
141 stack->frames = top;
142 return stack;
143}
144
145ScopedReportBase::ScopedReportBase(ReportType typ, uptr tag) {
146 ctx->thread_registry->CheckLocked();
147 void *mem = internal_alloc(MBlockReport, sizeof(ReportDesc));
148 rep_ = new(mem) ReportDesc;
149 rep_->typ = typ;
150 rep_->tag = tag;
151 ctx->report_mtx.Lock();
152}
153
154ScopedReportBase::~ScopedReportBase() {
155 ctx->report_mtx.Unlock();
156 DestroyAndFree(rep_);
157 rep_ = nullptr;
158}
159
160void ScopedReportBase::AddStack(StackTrace stack, bool suppressable) {
161 ReportStack **rs = rep_->stacks.PushBack();
162 *rs = SymbolizeStack(stack);
163 (*rs)->suppressable = suppressable;
164}
165
166void ScopedReportBase::AddMemoryAccess(uptr addr, uptr external_tag, Shadow s,
167 StackTrace stack, const MutexSet *mset) {
168 void *mem = internal_alloc(MBlockReportMop, sizeof(ReportMop));
169 ReportMop *mop = new(mem) ReportMop;
170 rep_->mops.PushBack(mop);
171 mop->tid = s.tid();
172 mop->addr = addr + s.addr0();
173 mop->size = s.size();
174 mop->write = s.IsWrite();
175 mop->atomic = s.IsAtomic();
176 mop->stack = SymbolizeStack(stack);
177 mop->external_tag = external_tag;
178 if (mop->stack)
179 mop->stack->suppressable = true;
180 for (uptr i = 0; i < mset->Size(); i++) {
181 MutexSet::Desc d = mset->Get(i);
182 u64 mid = this->AddMutex(d.id);
183 ReportMopMutex mtx = {mid, d.write};
184 mop->mset.PushBack(mtx);
185 }
186}
187
188void ScopedReportBase::AddUniqueTid(int unique_tid) {
189 rep_->unique_tids.PushBack(unique_tid);
190}
191
192void ScopedReportBase::AddThread(const ThreadContext *tctx, bool suppressable) {
193 for (uptr i = 0; i < rep_->threads.Size(); i++) {
194 if ((u32)rep_->threads[i]->id == tctx->tid)
195 return;
196 }
197 void *mem = internal_alloc(MBlockReportThread, sizeof(ReportThread));
198 ReportThread *rt = new(mem) ReportThread;
199 rep_->threads.PushBack(rt);
200 rt->id = tctx->tid;
201 rt->os_id = tctx->os_id;
202 rt->running = (tctx->status == ThreadStatusRunning);
203 rt->name = internal_strdup(tctx->name);
204 rt->parent_tid = tctx->parent_tid;
205 rt->thread_type = tctx->thread_type;
206 rt->stack = 0;
207 rt->stack = SymbolizeStackId(tctx->creation_stack_id);
208 if (rt->stack)
209 rt->stack->suppressable = suppressable;
210}
211
212#if !SANITIZER_GO
213static bool FindThreadByUidLockedCallback(ThreadContextBase *tctx, void *arg) {
214 int unique_id = *(int *)arg;
215 return tctx->unique_id == (u32)unique_id;
216}
217
218static ThreadContext *FindThreadByUidLocked(int unique_id) {
219 ctx->thread_registry->CheckLocked();
220 return static_cast<ThreadContext *>(
221 ctx->thread_registry->FindThreadContextLocked(
222 FindThreadByUidLockedCallback, &unique_id));
223}
224
225static ThreadContext *FindThreadByTidLocked(int tid) {
226 ctx->thread_registry->CheckLocked();
227 return static_cast<ThreadContext*>(
228 ctx->thread_registry->GetThreadLocked(tid));
229}
230
231static bool IsInStackOrTls(ThreadContextBase *tctx_base, void *arg) {
232 uptr addr = (uptr)arg;
233 ThreadContext *tctx = static_cast<ThreadContext*>(tctx_base);
234 if (tctx->status != ThreadStatusRunning)
235 return false;
236 ThreadState *thr = tctx->thr;
237 CHECK(thr);
238 return ((addr >= thr->stk_addr && addr < thr->stk_addr + thr->stk_size) ||
239 (addr >= thr->tls_addr && addr < thr->tls_addr + thr->tls_size));
240}
241
242ThreadContext *IsThreadStackOrTls(uptr addr, bool *is_stack) {
243 ctx->thread_registry->CheckLocked();
244 ThreadContext *tctx = static_cast<ThreadContext*>(
245 ctx->thread_registry->FindThreadContextLocked(IsInStackOrTls,
246 (void*)addr));
247 if (!tctx)
248 return 0;
249 ThreadState *thr = tctx->thr;
250 CHECK(thr);
251 *is_stack = (addr >= thr->stk_addr && addr < thr->stk_addr + thr->stk_size);
252 return tctx;
253}
254#endif
255
256void ScopedReportBase::AddThread(int unique_tid, bool suppressable) {
257#if !SANITIZER_GO
258 if (const ThreadContext *tctx = FindThreadByUidLocked(unique_tid))
259 AddThread(tctx, suppressable);
260#endif
261}
262
263void ScopedReportBase::AddMutex(const SyncVar *s) {
264 for (uptr i = 0; i < rep_->mutexes.Size(); i++) {
265 if (rep_->mutexes[i]->id == s->uid)
266 return;
267 }
268 void *mem = internal_alloc(MBlockReportMutex, sizeof(ReportMutex));
269 ReportMutex *rm = new(mem) ReportMutex;
270 rep_->mutexes.PushBack(rm);
271 rm->id = s->uid;
272 rm->addr = s->addr;
273 rm->destroyed = false;
274 rm->stack = SymbolizeStackId(s->creation_stack_id);
275}
276
277u64 ScopedReportBase::AddMutex(u64 id) {
278 u64 uid = 0;
279 u64 mid = id;
280 uptr addr = SyncVar::SplitId(id, &uid);
281 SyncVar *s = ctx->metamap.GetIfExistsAndLock(addr, true);
282 // Check that the mutex is still alive.
283 // Another mutex can be created at the same address,
284 // so check uid as well.
285 if (s && s->CheckId(uid)) {
286 mid = s->uid;
287 AddMutex(s);
288 } else {
289 AddDeadMutex(id);
290 }
291 if (s)
292 s->mtx.Unlock();
293 return mid;
294}
295
296void ScopedReportBase::AddDeadMutex(u64 id) {
297 for (uptr i = 0; i < rep_->mutexes.Size(); i++) {
298 if (rep_->mutexes[i]->id == id)
299 return;
300 }
301 void *mem = internal_alloc(MBlockReportMutex, sizeof(ReportMutex));
302 ReportMutex *rm = new(mem) ReportMutex;
303 rep_->mutexes.PushBack(rm);
304 rm->id = id;
305 rm->addr = 0;
306 rm->destroyed = true;
307 rm->stack = 0;
308}
309
310void ScopedReportBase::AddLocation(uptr addr, uptr size) {
311 if (addr == 0)
312 return;
313#if !SANITIZER_GO
314 int fd = -1;
315 int creat_tid = kInvalidTid;
316 u32 creat_stack = 0;
317 if (FdLocation(addr, &fd, &creat_tid, &creat_stack)) {
318 ReportLocation *loc = ReportLocation::New(ReportLocationFD);
319 loc->fd = fd;
320 loc->tid = creat_tid;
321 loc->stack = SymbolizeStackId(creat_stack);
322 rep_->locs.PushBack(loc);
323 ThreadContext *tctx = FindThreadByUidLocked(creat_tid);
324 if (tctx)
325 AddThread(tctx);
326 return;
327 }
328 MBlock *b = 0;
329 Allocator *a = allocator();
330 if (a->PointerIsMine((void*)addr)) {
331 void *block_begin = a->GetBlockBegin((void*)addr);
332 if (block_begin)
333 b = ctx->metamap.GetBlock((uptr)block_begin);
334 }
335 if (b != 0) {
336 ThreadContext *tctx = FindThreadByTidLocked(b->tid);
337 ReportLocation *loc = ReportLocation::New(ReportLocationHeap);
338 loc->heap_chunk_start = (uptr)allocator()->GetBlockBegin((void *)addr);
339 loc->heap_chunk_size = b->siz;
340 loc->external_tag = b->tag;
341 loc->tid = tctx ? tctx->tid : b->tid;
342 loc->stack = SymbolizeStackId(b->stk);
343 rep_->locs.PushBack(loc);
344 if (tctx)
345 AddThread(tctx);
346 return;
347 }
348 bool is_stack = false;
349 if (ThreadContext *tctx = IsThreadStackOrTls(addr, &is_stack)) {
350 ReportLocation *loc =
351 ReportLocation::New(is_stack ? ReportLocationStack : ReportLocationTLS);
352 loc->tid = tctx->tid;
353 rep_->locs.PushBack(loc);
354 AddThread(tctx);
355 }
356#endif
357 if (ReportLocation *loc = SymbolizeData(addr)) {
358 loc->suppressable = true;
359 rep_->locs.PushBack(loc);
360 return;
361 }
362}
363
364#if !SANITIZER_GO
365void ScopedReportBase::AddSleep(u32 stack_id) {
366 rep_->sleep = SymbolizeStackId(stack_id);
367}
368#endif
369
370void ScopedReportBase::SetCount(int count) { rep_->count = count; }
371
372const ReportDesc *ScopedReportBase::GetReport() const { return rep_; }
373
374ScopedReport::ScopedReport(ReportType typ, uptr tag)
375 : ScopedReportBase(typ, tag) {}
376
377ScopedReport::~ScopedReport() {}
378
379void RestoreStack(int tid, const u64 epoch, VarSizeStackTrace *stk,
380 MutexSet *mset, uptr *tag) {
381 // This function restores stack trace and mutex set for the thread/epoch.
382 // It does so by getting stack trace and mutex set at the beginning of
383 // trace part, and then replaying the trace till the given epoch.
384 Trace* trace = ThreadTrace(tid);
385 ReadLock l(&trace->mtx);
386 const int partidx = (epoch / kTracePartSize) % TraceParts();
387 TraceHeader* hdr = &trace->headers[partidx];
388 if (epoch < hdr->epoch0 || epoch >= hdr->epoch0 + kTracePartSize)
389 return;
390 CHECK_EQ(RoundDown(epoch, kTracePartSize), hdr->epoch0);
391 const u64 epoch0 = RoundDown(epoch, TraceSize());
392 const u64 eend = epoch % TraceSize();
393 const u64 ebegin = RoundDown(eend, kTracePartSize);
394 DPrintf("#%d: RestoreStack epoch=%zu ebegin=%zu eend=%zu partidx=%d\n",
395 tid, (uptr)epoch, (uptr)ebegin, (uptr)eend, partidx);
396 Vector<uptr> stack;
397 stack.Resize(hdr->stack0.size + 64);
398 for (uptr i = 0; i < hdr->stack0.size; i++) {
399 stack[i] = hdr->stack0.trace[i];
400 DPrintf2(" #%02zu: pc=%zx\n", i, stack[i]);
401 }
402 if (mset)
403 *mset = hdr->mset0;
404 uptr pos = hdr->stack0.size;
405 Event *events = (Event*)GetThreadTrace(tid);
406 for (uptr i = ebegin; i <= eend; i++) {
407 Event ev = events[i];
408 EventType typ = (EventType)(ev >> kEventPCBits);
409 uptr pc = (uptr)(ev & ((1ull << kEventPCBits) - 1));
410 DPrintf2(" %zu typ=%d pc=%zx\n", i, typ, pc);
411 if (typ == EventTypeMop) {
412 stack[pos] = pc;
413 } else if (typ == EventTypeFuncEnter) {
414 if (stack.Size() < pos + 2)
415 stack.Resize(pos + 2);
416 stack[pos++] = pc;
417 } else if (typ == EventTypeFuncExit) {
418 if (pos > 0)
419 pos--;
420 }
421 if (mset) {
422 if (typ == EventTypeLock) {
423 mset->Add(pc, true, epoch0 + i);
424 } else if (typ == EventTypeUnlock) {
425 mset->Del(pc, true);
426 } else if (typ == EventTypeRLock) {
427 mset->Add(pc, false, epoch0 + i);
428 } else if (typ == EventTypeRUnlock) {
429 mset->Del(pc, false);
430 }
431 }
432 for (uptr j = 0; j <= pos; j++)
433 DPrintf2(" #%zu: %zx\n", j, stack[j]);
434 }
435 if (pos == 0 && stack[0] == 0)
436 return;
437 pos++;
438 stk->Init(&stack[0], pos);
439 ExtractTagFromStack(stk, tag);
440}
441
442static bool FindRacyStacks(const RacyStacks &hash) {
443 for (uptr i = 0; i < ctx->racy_stacks.Size(); i++) {
444 if (hash == ctx->racy_stacks[i]) {
445 VPrintf(2, "ThreadSanitizer: suppressing report as doubled (stack)\n");
446 return true;
447 }
448 }
449 return false;
450}
451
452static bool HandleRacyStacks(ThreadState *thr, VarSizeStackTrace traces[2]) {
453 if (!flags()->suppress_equal_stacks)
454 return false;
455 RacyStacks hash;
456 hash.hash[0] = md5_hash(traces[0].trace, traces[0].size * sizeof(uptr));
457 hash.hash[1] = md5_hash(traces[1].trace, traces[1].size * sizeof(uptr));
458 {
459 ReadLock lock(&ctx->racy_mtx);
460 if (FindRacyStacks(hash))
461 return true;
462 }
463 Lock lock(&ctx->racy_mtx);
464 if (FindRacyStacks(hash))
465 return true;
466 ctx->racy_stacks.PushBack(hash);
467 return false;
468}
469
470static bool FindRacyAddress(const RacyAddress &ra0) {
471 for (uptr i = 0; i < ctx->racy_addresses.Size(); i++) {
472 RacyAddress ra2 = ctx->racy_addresses[i];
473 uptr maxbeg = max(ra0.addr_min, ra2.addr_min);
474 uptr minend = min(ra0.addr_max, ra2.addr_max);
475 if (maxbeg < minend) {
476 VPrintf(2, "ThreadSanitizer: suppressing report as doubled (addr)\n");
477 return true;
478 }
479 }
480 return false;
481}
482
483static bool HandleRacyAddress(ThreadState *thr, uptr addr_min, uptr addr_max) {
484 if (!flags()->suppress_equal_addresses)
485 return false;
486 RacyAddress ra0 = {addr_min, addr_max};
487 {
488 ReadLock lock(&ctx->racy_mtx);
489 if (FindRacyAddress(ra0))
490 return true;
491 }
492 Lock lock(&ctx->racy_mtx);
493 if (FindRacyAddress(ra0))
494 return true;
495 ctx->racy_addresses.PushBack(ra0);
496 return false;
497}
498
499bool OutputReport(ThreadState *thr, const ScopedReport &srep) {
500 if (!flags()->report_bugs || thr->suppress_reports)
501 return false;
502 atomic_store_relaxed(&ctx->last_symbolize_time_ns, NanoTime());
503 const ReportDesc *rep = srep.GetReport();
504 CHECK_EQ(thr->current_report, nullptr);
505 thr->current_report = rep;
506 Suppression *supp = 0;
507 uptr pc_or_addr = 0;
508 for (uptr i = 0; pc_or_addr == 0 && i < rep->mops.Size(); i++)
509 pc_or_addr = IsSuppressed(rep->typ, rep->mops[i]->stack, &supp);
510 for (uptr i = 0; pc_or_addr == 0 && i < rep->stacks.Size(); i++)
511 pc_or_addr = IsSuppressed(rep->typ, rep->stacks[i], &supp);
512 for (uptr i = 0; pc_or_addr == 0 && i < rep->threads.Size(); i++)
513 pc_or_addr = IsSuppressed(rep->typ, rep->threads[i]->stack, &supp);
514 for (uptr i = 0; pc_or_addr == 0 && i < rep->locs.Size(); i++)
515 pc_or_addr = IsSuppressed(rep->typ, rep->locs[i], &supp);
516 if (pc_or_addr != 0) {
517 Lock lock(&ctx->fired_suppressions_mtx);
518 FiredSuppression s = {srep.GetReport()->typ, pc_or_addr, supp};
519 ctx->fired_suppressions.push_back(s);
520 }
521 {
522 bool old_is_freeing = thr->is_freeing;
523 thr->is_freeing = false;
524 bool suppressed = OnReport(rep, pc_or_addr != 0);
525 thr->is_freeing = old_is_freeing;
526 if (suppressed) {
527 thr->current_report = nullptr;
528 return false;
529 }
530 }
531 PrintReport(rep);
532 __tsan_on_report(rep);
533 ctx->nreported++;
534 if (flags()->halt_on_error)
535 Die();
536 thr->current_report = nullptr;
537 return true;
538}
539
540bool IsFiredSuppression(Context *ctx, ReportType type, StackTrace trace) {
541 ReadLock lock(&ctx->fired_suppressions_mtx);
542 for (uptr k = 0; k < ctx->fired_suppressions.size(); k++) {
543 if (ctx->fired_suppressions[k].type != type)
544 continue;
545 for (uptr j = 0; j < trace.size; j++) {
546 FiredSuppression *s = &ctx->fired_suppressions[k];
547 if (trace.trace[j] == s->pc_or_addr) {
548 if (s->supp)
549 atomic_fetch_add(&s->supp->hit_count, 1, memory_order_relaxed);
550 return true;
551 }
552 }
553 }
554 return false;
555}
556
557static bool IsFiredSuppression(Context *ctx, ReportType type, uptr addr) {
558 ReadLock lock(&ctx->fired_suppressions_mtx);
559 for (uptr k = 0; k < ctx->fired_suppressions.size(); k++) {
560 if (ctx->fired_suppressions[k].type != type)
561 continue;
562 FiredSuppression *s = &ctx->fired_suppressions[k];
563 if (addr == s->pc_or_addr) {
564 if (s->supp)
565 atomic_fetch_add(&s->supp->hit_count, 1, memory_order_relaxed);
566 return true;
567 }
568 }
569 return false;
570}
571
572static bool RaceBetweenAtomicAndFree(ThreadState *thr) {
573 Shadow s0(thr->racy_state[0]);
574 Shadow s1(thr->racy_state[1]);
575 CHECK(!(s0.IsAtomic() && s1.IsAtomic()));
576 if (!s0.IsAtomic() && !s1.IsAtomic())
577 return true;
578 if (s0.IsAtomic() && s1.IsFreed())
579 return true;
580 if (s1.IsAtomic() && thr->is_freeing)
581 return true;
582 return false;
583}
584
585void ReportRace(ThreadState *thr) {
586 CheckNoLocks(thr);
587
588 // Symbolizer makes lots of intercepted calls. If we try to process them,
589 // at best it will cause deadlocks on internal mutexes.
590 ScopedIgnoreInterceptors ignore;
591
592 if (!flags()->report_bugs)
593 return;
594 if (!flags()->report_atomic_races && !RaceBetweenAtomicAndFree(thr))
595 return;
596
597 bool freed = false;
598 {
599 Shadow s(thr->racy_state[1]);
600 freed = s.GetFreedAndReset();
601 thr->racy_state[1] = s.raw();
602 }
603
604 uptr addr = ShadowToMem((uptr)thr->racy_shadow_addr);
605 uptr addr_min = 0;
606 uptr addr_max = 0;
607 {
608 uptr a0 = addr + Shadow(thr->racy_state[0]).addr0();
609 uptr a1 = addr + Shadow(thr->racy_state[1]).addr0();
610 uptr e0 = a0 + Shadow(thr->racy_state[0]).size();
611 uptr e1 = a1 + Shadow(thr->racy_state[1]).size();
612 addr_min = min(a0, a1);
613 addr_max = max(e0, e1);
614 if (IsExpectedReport(addr_min, addr_max - addr_min))
615 return;
616 }
617 if (HandleRacyAddress(thr, addr_min, addr_max))
618 return;
619
620 ReportType typ = ReportTypeRace;
621 if (thr->is_vptr_access && freed)
622 typ = ReportTypeVptrUseAfterFree;
623 else if (thr->is_vptr_access)
624 typ = ReportTypeVptrRace;
625 else if (freed)
626 typ = ReportTypeUseAfterFree;
627
628 if (IsFiredSuppression(ctx, typ, addr))
629 return;
630
631 const uptr kMop = 2;
632 VarSizeStackTrace traces[kMop];
633 uptr tags[kMop] = {kExternalTagNone};
634 uptr toppc = TraceTopPC(thr);
635 if (toppc >> kEventPCBits) {
636 // This is a work-around for a known issue.
637 // The scenario where this happens is rather elaborate and requires
638 // an instrumented __sanitizer_report_error_summary callback and
639 // a __tsan_symbolize_external callback and a race during a range memory
640 // access larger than 8 bytes. MemoryAccessRange adds the current PC to
641 // the trace and starts processing memory accesses. A first memory access
642 // triggers a race, we report it and call the instrumented
643 // __sanitizer_report_error_summary, which adds more stuff to the trace
644 // since it is intrumented. Then a second memory access in MemoryAccessRange
645 // also triggers a race and we get here and call TraceTopPC to get the
646 // current PC, however now it contains some unrelated events from the
647 // callback. Most likely, TraceTopPC will now return a EventTypeFuncExit
648 // event. Later we subtract -1 from it (in GetPreviousInstructionPc)
649 // and the resulting PC has kExternalPCBit set, so we pass it to
650 // __tsan_symbolize_external_ex. __tsan_symbolize_external_ex is within its
651 // rights to crash since the PC is completely bogus.
652 // test/tsan/double_race.cpp contains a test case for this.
653 toppc = 0;
654 }
655 ObtainCurrentStack(thr, toppc, &traces[0], &tags[0]);
656 if (IsFiredSuppression(ctx, typ, traces[0]))
657 return;
658
659 // MutexSet is too large to live on stack.
660 Vector<u64> mset_buffer;
661 mset_buffer.Resize(sizeof(MutexSet) / sizeof(u64) + 1);
662 MutexSet *mset2 = new(&mset_buffer[0]) MutexSet();
663
664 Shadow s2(thr->racy_state[1]);
665 RestoreStack(s2.tid(), s2.epoch(), &traces[1], mset2, &tags[1]);
666 if (IsFiredSuppression(ctx, typ, traces[1]))
667 return;
668
669 if (HandleRacyStacks(thr, traces))
670 return;
671
672 // If any of the accesses has a tag, treat this as an "external" race.
673 uptr tag = kExternalTagNone;
674 for (uptr i = 0; i < kMop; i++) {
675 if (tags[i] != kExternalTagNone) {
676 typ = ReportTypeExternalRace;
677 tag = tags[i];
678 break;
679 }
680 }
681
682 ThreadRegistryLock l0(ctx->thread_registry);
683 ScopedReport rep(typ, tag);
684 for (uptr i = 0; i < kMop; i++) {
685 Shadow s(thr->racy_state[i]);
686 rep.AddMemoryAccess(addr, tags[i], s, traces[i],
687 i == 0 ? &thr->mset : mset2);
688 }
689
690 for (uptr i = 0; i < kMop; i++) {
691 FastState s(thr->racy_state[i]);
692 ThreadContext *tctx = static_cast<ThreadContext*>(
693 ctx->thread_registry->GetThreadLocked(s.tid()));
694 if (s.epoch() < tctx->epoch0 || s.epoch() > tctx->epoch1)
695 continue;
696 rep.AddThread(tctx);
697 }
698
699 rep.AddLocation(addr_min, addr_max - addr_min);
700
701#if !SANITIZER_GO
702 {
703 Shadow s(thr->racy_state[1]);
704 if (s.epoch() <= thr->last_sleep_clock.get(s.tid()))
705 rep.AddSleep(thr->last_sleep_stack_id);
706 }
707#endif
708
709 if (!OutputReport(thr, rep))
710 return;
711
712}
713
714void PrintCurrentStack(ThreadState *thr, uptr pc) {
715 VarSizeStackTrace trace;
716 ObtainCurrentStack(thr, pc, &trace);
717 PrintStack(SymbolizeStack(trace));
718}
719
720// Always inlining PrintCurrentStackSlow, because LocatePcInTrace assumes
721// __sanitizer_print_stack_trace exists in the actual unwinded stack, but
722// tail-call to PrintCurrentStackSlow breaks this assumption because
723// __sanitizer_print_stack_trace disappears after tail-call.
724// However, this solution is not reliable enough, please see dvyukov's comment
725// http://reviews.llvm.org/D19148#406208
726// Also see PR27280 comment 2 and 3 for breaking examples and analysis.
727ALWAYS_INLINE
728void PrintCurrentStackSlow(uptr pc) {
729#if !SANITIZER_GO
730 uptr bp = GET_CURRENT_FRAME();
731 BufferedStackTrace *ptrace =
732 new(internal_alloc(MBlockStackTrace, sizeof(BufferedStackTrace)))
733 BufferedStackTrace();
734 ptrace->Unwind(pc, bp, nullptr, false);
735
736 for (uptr i = 0; i < ptrace->size / 2; i++) {
737 uptr tmp = ptrace->trace_buffer[i];
738 ptrace->trace_buffer[i] = ptrace->trace_buffer[ptrace->size - i - 1];
739 ptrace->trace_buffer[ptrace->size - i - 1] = tmp;
740 }
741 PrintStack(SymbolizeStack(*ptrace));
742#endif
743}
744
745} // namespace __tsan
746
747using namespace __tsan;
748
749extern "C" {
750SANITIZER_INTERFACE_ATTRIBUTE
751void __sanitizer_print_stack_trace() {
752 PrintCurrentStackSlow(StackTrace::GetCurrentPc());
753}
754} // extern "C"
lib/tsan/tsan_rtl_thread.cpp created+462
...@@ -0,0 +1,462 @@
1//===-- tsan_rtl_thread.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#include "sanitizer_common/sanitizer_placement_new.h"
14#include "tsan_rtl.h"
15#include "tsan_mman.h"
16#include "tsan_platform.h"
17#include "tsan_report.h"
18#include "tsan_sync.h"
19
20namespace __tsan {
21
22// ThreadContext implementation.
23
24ThreadContext::ThreadContext(int tid)
25 : ThreadContextBase(tid)
26 , thr()
27 , sync()
28 , epoch0()
29 , epoch1() {
30}
31
32#if !SANITIZER_GO
33ThreadContext::~ThreadContext() {
34}
35#endif
36
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 == 0)
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 if (reuse_count == 0)
65 StatInc(args->thr, StatThreadMaxTid);
66}
67
68void ThreadContext::OnReset() {
69 CHECK_EQ(sync.size(), 0);
70 uptr trace_p = GetThreadTrace(tid);
71 ReleaseMemoryPagesToOS(trace_p, trace_p + TraceSize() * sizeof(Event));
72 //!!! ReleaseMemoryToOS(GetThreadTraceHeader(tid), sizeof(Trace));
73}
74
75void ThreadContext::OnDetached(void *arg) {
76 ThreadState *thr1 = static_cast<ThreadState*>(arg);
77 sync.Reset(&thr1->proc()->clock_cache);
78}
79
80struct OnStartedArgs {
81 ThreadState *thr;
82 uptr stk_addr;
83 uptr stk_size;
84 uptr tls_addr;
85 uptr tls_size;
86};
87
88void ThreadContext::OnStarted(void *arg) {
89 OnStartedArgs *args = static_cast<OnStartedArgs*>(arg);
90 thr = args->thr;
91 // RoundUp so that one trace part does not contain events
92 // from different threads.
93 epoch0 = RoundUp(epoch1 + 1, kTracePartSize);
94 epoch1 = (u64)-1;
95 new(thr) ThreadState(ctx, tid, unique_id, epoch0, reuse_count,
96 args->stk_addr, args->stk_size, args->tls_addr, args->tls_size);
97#if !SANITIZER_GO
98 thr->shadow_stack = &ThreadTrace(thr->tid)->shadow_stack[0];
99 thr->shadow_stack_pos = thr->shadow_stack;
100 thr->shadow_stack_end = thr->shadow_stack + kShadowStackSize;
101#else
102 // Setup dynamic shadow stack.
103 const int kInitStackSize = 8;
104 thr->shadow_stack = (uptr*)internal_alloc(MBlockShadowStack,
105 kInitStackSize * sizeof(uptr));
106 thr->shadow_stack_pos = thr->shadow_stack;
107 thr->shadow_stack_end = thr->shadow_stack + kInitStackSize;
108#endif
109 if (common_flags()->detect_deadlocks)
110 thr->dd_lt = ctx->dd->CreateLogicalThread(unique_id);
111 thr->fast_state.SetHistorySize(flags()->history_size);
112 // Commit switch to the new part of the trace.
113 // TraceAddEvent will reset stack0/mset0 in the new part for us.
114 TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
115
116 thr->fast_synch_epoch = epoch0;
117 AcquireImpl(thr, 0, &sync);
118 StatInc(thr, StatSyncAcquire);
119 sync.Reset(&thr->proc()->clock_cache);
120 thr->is_inited = true;
121 DPrintf("#%d: ThreadStart epoch=%zu stk_addr=%zx stk_size=%zx "
122 "tls_addr=%zx tls_size=%zx\n",
123 tid, (uptr)epoch0, args->stk_addr, args->stk_size,
124 args->tls_addr, args->tls_size);
125}
126
127void ThreadContext::OnFinished() {
128#if SANITIZER_GO
129 internal_free(thr->shadow_stack);
130 thr->shadow_stack = nullptr;
131 thr->shadow_stack_pos = nullptr;
132 thr->shadow_stack_end = nullptr;
133#endif
134 if (!detached) {
135 thr->fast_state.IncrementEpoch();
136 // Can't increment epoch w/o writing to the trace as well.
137 TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
138 ReleaseImpl(thr, 0, &sync);
139 }
140 epoch1 = thr->fast_state.epoch();
141
142 if (common_flags()->detect_deadlocks)
143 ctx->dd->DestroyLogicalThread(thr->dd_lt);
144 thr->clock.ResetCached(&thr->proc()->clock_cache);
145#if !SANITIZER_GO
146 thr->last_sleep_clock.ResetCached(&thr->proc()->clock_cache);
147#endif
148#if !SANITIZER_GO
149 PlatformCleanUpThreadState(thr);
150#endif
151 thr->~ThreadState();
152#if TSAN_COLLECT_STATS
153 StatAggregate(ctx->stat, thr->stat);
154#endif
155 thr = 0;
156}
157
158#if !SANITIZER_GO
159struct ThreadLeak {
160 ThreadContext *tctx;
161 int count;
162};
163
164static void MaybeReportThreadLeak(ThreadContextBase *tctx_base, void *arg) {
165 Vector<ThreadLeak> &leaks = *(Vector<ThreadLeak>*)arg;
166 ThreadContext *tctx = static_cast<ThreadContext*>(tctx_base);
167 if (tctx->detached || tctx->status != ThreadStatusFinished)
168 return;
169 for (uptr i = 0; i < leaks.Size(); i++) {
170 if (leaks[i].tctx->creation_stack_id == tctx->creation_stack_id) {
171 leaks[i].count++;
172 return;
173 }
174 }
175 ThreadLeak leak = {tctx, 1};
176 leaks.PushBack(leak);
177}
178#endif
179
180#if !SANITIZER_GO
181static void ReportIgnoresEnabled(ThreadContext *tctx, IgnoreSet *set) {
182 if (tctx->tid == 0) {
183 Printf("ThreadSanitizer: main thread finished with ignores enabled\n");
184 } else {
185 Printf("ThreadSanitizer: thread T%d %s finished with ignores enabled,"
186 " created at:\n", tctx->tid, tctx->name);
187 PrintStack(SymbolizeStackId(tctx->creation_stack_id));
188 }
189 Printf(" One of the following ignores was not ended"
190 " (in order of probability)\n");
191 for (uptr i = 0; i < set->Size(); i++) {
192 Printf(" Ignore was enabled at:\n");
193 PrintStack(SymbolizeStackId(set->At(i)));
194 }
195 Die();
196}
197
198static void ThreadCheckIgnore(ThreadState *thr) {
199 if (ctx->after_multithreaded_fork)
200 return;
201 if (thr->ignore_reads_and_writes)
202 ReportIgnoresEnabled(thr->tctx, &thr->mop_ignore_set);
203 if (thr->ignore_sync)
204 ReportIgnoresEnabled(thr->tctx, &thr->sync_ignore_set);
205}
206#else
207static void ThreadCheckIgnore(ThreadState *thr) {}
208#endif
209
210void ThreadFinalize(ThreadState *thr) {
211 ThreadCheckIgnore(thr);
212#if !SANITIZER_GO
213 if (!flags()->report_thread_leaks)
214 return;
215 ThreadRegistryLock l(ctx->thread_registry);
216 Vector<ThreadLeak> leaks;
217 ctx->thread_registry->RunCallbackForEachThreadLocked(
218 MaybeReportThreadLeak, &leaks);
219 for (uptr i = 0; i < leaks.Size(); i++) {
220 ScopedReport rep(ReportTypeThreadLeak);
221 rep.AddThread(leaks[i].tctx, true);
222 rep.SetCount(leaks[i].count);
223 OutputReport(thr, rep);
224 }
225#endif
226}
227
228int ThreadCount(ThreadState *thr) {
229 uptr result;
230 ctx->thread_registry->GetNumberOfThreads(0, 0, &result);
231 return (int)result;
232}
233
234int ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached) {
235 StatInc(thr, StatThreadCreate);
236 OnCreatedArgs args = { thr, pc };
237 u32 parent_tid = thr ? thr->tid : kInvalidTid; // No parent for GCD workers.
238 int tid =
239 ctx->thread_registry->CreateThread(uid, detached, parent_tid, &args);
240 DPrintf("#%d: ThreadCreate tid=%d uid=%zu\n", parent_tid, tid, uid);
241 StatSet(thr, StatThreadMaxAlive, ctx->thread_registry->GetMaxAliveThreads());
242 return tid;
243}
244
245void ThreadStart(ThreadState *thr, int tid, tid_t os_id,
246 ThreadType thread_type) {
247 uptr stk_addr = 0;
248 uptr stk_size = 0;
249 uptr tls_addr = 0;
250 uptr tls_size = 0;
251#if !SANITIZER_GO
252 if (thread_type != ThreadType::Fiber)
253 GetThreadStackAndTls(tid == 0, &stk_addr, &stk_size, &tls_addr, &tls_size);
254
255 if (tid) {
256 if (stk_addr && stk_size)
257 MemoryRangeImitateWrite(thr, /*pc=*/ 1, stk_addr, stk_size);
258
259 if (tls_addr && tls_size) ImitateTlsWrite(thr, tls_addr, tls_size);
260 }
261#endif
262
263 ThreadRegistry *tr = ctx->thread_registry;
264 OnStartedArgs args = { thr, stk_addr, stk_size, tls_addr, tls_size };
265 tr->StartThread(tid, os_id, thread_type, &args);
266
267 tr->Lock();
268 thr->tctx = (ThreadContext*)tr->GetThreadLocked(tid);
269 tr->Unlock();
270
271#if !SANITIZER_GO
272 if (ctx->after_multithreaded_fork) {
273 thr->ignore_interceptors++;
274 ThreadIgnoreBegin(thr, 0);
275 ThreadIgnoreSyncBegin(thr, 0);
276 }
277#endif
278}
279
280void ThreadFinish(ThreadState *thr) {
281 ThreadCheckIgnore(thr);
282 StatInc(thr, StatThreadFinish);
283 if (thr->stk_addr && thr->stk_size)
284 DontNeedShadowFor(thr->stk_addr, thr->stk_size);
285 if (thr->tls_addr && thr->tls_size)
286 DontNeedShadowFor(thr->tls_addr, thr->tls_size);
287 thr->is_dead = true;
288 ctx->thread_registry->FinishThread(thr->tid);
289}
290
291struct ConsumeThreadContext {
292 uptr uid;
293 ThreadContextBase *tctx;
294};
295
296static bool ConsumeThreadByUid(ThreadContextBase *tctx, void *arg) {
297 ConsumeThreadContext *findCtx = (ConsumeThreadContext *)arg;
298 if (tctx->user_id == findCtx->uid && tctx->status != ThreadStatusInvalid) {
299 if (findCtx->tctx) {
300 // Ensure that user_id is unique. If it's not the case we are screwed.
301 // Something went wrong before, but now there is no way to recover.
302 // Returning a wrong thread is not an option, it may lead to very hard
303 // to debug false positives (e.g. if we join a wrong thread).
304 Report("ThreadSanitizer: dup thread with used id 0x%zx\n", findCtx->uid);
305 Die();
306 }
307 findCtx->tctx = tctx;
308 tctx->user_id = 0;
309 }
310 return false;
311}
312
313int ThreadConsumeTid(ThreadState *thr, uptr pc, uptr uid) {
314 ConsumeThreadContext findCtx = {uid, nullptr};
315 ctx->thread_registry->FindThread(ConsumeThreadByUid, &findCtx);
316 int tid = findCtx.tctx ? findCtx.tctx->tid : ThreadRegistry::kUnknownTid;
317 DPrintf("#%d: ThreadTid uid=%zu tid=%d\n", thr->tid, uid, tid);
318 return tid;
319}
320
321void ThreadJoin(ThreadState *thr, uptr pc, int tid) {
322 CHECK_GT(tid, 0);
323 CHECK_LT(tid, kMaxTid);
324 DPrintf("#%d: ThreadJoin tid=%d\n", thr->tid, tid);
325 ctx->thread_registry->JoinThread(tid, thr);
326}
327
328void ThreadDetach(ThreadState *thr, uptr pc, int tid) {
329 CHECK_GT(tid, 0);
330 CHECK_LT(tid, kMaxTid);
331 ctx->thread_registry->DetachThread(tid, thr);
332}
333
334void ThreadNotJoined(ThreadState *thr, uptr pc, int tid, uptr uid) {
335 CHECK_GT(tid, 0);
336 CHECK_LT(tid, kMaxTid);
337 ctx->thread_registry->SetThreadUserId(tid, uid);
338}
339
340void ThreadSetName(ThreadState *thr, const char *name) {
341 ctx->thread_registry->SetThreadName(thr->tid, name);
342}
343
344void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr,
345 uptr size, bool is_write) {
346 if (size == 0)
347 return;
348
349 u64 *shadow_mem = (u64*)MemToShadow(addr);
350 DPrintf2("#%d: MemoryAccessRange: @%p %p size=%d is_write=%d\n",
351 thr->tid, (void*)pc, (void*)addr,
352 (int)size, is_write);
353
354#if SANITIZER_DEBUG
355 if (!IsAppMem(addr)) {
356 Printf("Access to non app mem %zx\n", addr);
357 DCHECK(IsAppMem(addr));
358 }
359 if (!IsAppMem(addr + size - 1)) {
360 Printf("Access to non app mem %zx\n", addr + size - 1);
361 DCHECK(IsAppMem(addr + size - 1));
362 }
363 if (!IsShadowMem((uptr)shadow_mem)) {
364 Printf("Bad shadow addr %p (%zx)\n", shadow_mem, addr);
365 DCHECK(IsShadowMem((uptr)shadow_mem));
366 }
367 if (!IsShadowMem((uptr)(shadow_mem + size * kShadowCnt / 8 - 1))) {
368 Printf("Bad shadow addr %p (%zx)\n",
369 shadow_mem + size * kShadowCnt / 8 - 1, addr + size - 1);
370 DCHECK(IsShadowMem((uptr)(shadow_mem + size * kShadowCnt / 8 - 1)));
371 }
372#endif
373
374 StatInc(thr, StatMopRange);
375
376 if (*shadow_mem == kShadowRodata) {
377 DCHECK(!is_write);
378 // Access to .rodata section, no races here.
379 // Measurements show that it can be 10-20% of all memory accesses.
380 StatInc(thr, StatMopRangeRodata);
381 return;
382 }
383
384 FastState fast_state = thr->fast_state;
385 if (fast_state.GetIgnoreBit())
386 return;
387
388 fast_state.IncrementEpoch();
389 thr->fast_state = fast_state;
390 TraceAddEvent(thr, fast_state, EventTypeMop, pc);
391
392 bool unaligned = (addr % kShadowCell) != 0;
393
394 // Handle unaligned beginning, if any.
395 for (; addr % kShadowCell && size; addr++, size--) {
396 int const kAccessSizeLog = 0;
397 Shadow cur(fast_state);
398 cur.SetWrite(is_write);
399 cur.SetAddr0AndSizeLog(addr & (kShadowCell - 1), kAccessSizeLog);
400 MemoryAccessImpl(thr, addr, kAccessSizeLog, is_write, false,
401 shadow_mem, cur);
402 }
403 if (unaligned)
404 shadow_mem += kShadowCnt;
405 // Handle middle part, if any.
406 for (; size >= kShadowCell; addr += kShadowCell, size -= kShadowCell) {
407 int const kAccessSizeLog = 3;
408 Shadow cur(fast_state);
409 cur.SetWrite(is_write);
410 cur.SetAddr0AndSizeLog(0, kAccessSizeLog);
411 MemoryAccessImpl(thr, addr, kAccessSizeLog, is_write, false,
412 shadow_mem, cur);
413 shadow_mem += kShadowCnt;
414 }
415 // Handle ending, if any.
416 for (; size; addr++, size--) {
417 int const kAccessSizeLog = 0;
418 Shadow cur(fast_state);
419 cur.SetWrite(is_write);
420 cur.SetAddr0AndSizeLog(addr & (kShadowCell - 1), kAccessSizeLog);
421 MemoryAccessImpl(thr, addr, kAccessSizeLog, is_write, false,
422 shadow_mem, cur);
423 }
424}
425
426#if !SANITIZER_GO
427void FiberSwitchImpl(ThreadState *from, ThreadState *to) {
428 Processor *proc = from->proc();
429 ProcUnwire(proc, from);
430 ProcWire(proc, to);
431 set_cur_thread(to);
432}
433
434ThreadState *FiberCreate(ThreadState *thr, uptr pc, unsigned flags) {
435 void *mem = internal_alloc(MBlockThreadContex, sizeof(ThreadState));
436 ThreadState *fiber = static_cast<ThreadState *>(mem);
437 internal_memset(fiber, 0, sizeof(*fiber));
438 int tid = ThreadCreate(thr, pc, 0, true);
439 FiberSwitchImpl(thr, fiber);
440 ThreadStart(fiber, tid, 0, ThreadType::Fiber);
441 FiberSwitchImpl(fiber, thr);
442 return fiber;
443}
444
445void FiberDestroy(ThreadState *thr, uptr pc, ThreadState *fiber) {
446 FiberSwitchImpl(thr, fiber);
447 ThreadFinish(fiber);
448 FiberSwitchImpl(fiber, thr);
449 internal_free(fiber);
450}
451
452void FiberSwitch(ThreadState *thr, uptr pc,
453 ThreadState *fiber, unsigned flags) {
454 if (!(flags & FiberSwitchFlagNoSync))
455 Release(thr, pc, (uptr)fiber);
456 FiberSwitchImpl(thr, fiber);
457 if (!(flags & FiberSwitchFlagNoSync))
458 Acquire(fiber, pc, (uptr)fiber);
459}
460#endif
461
462} // namespace __tsan
lib/tsan/tsan_stack_trace.cpp created+63
...@@ -0,0 +1,63 @@
1//===-- tsan_stack_trace.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_stack_trace.h"
13#include "tsan_rtl.h"
14#include "tsan_mman.h"
15
16namespace __tsan {
17
18VarSizeStackTrace::VarSizeStackTrace()
19 : StackTrace(nullptr, 0), trace_buffer(nullptr) {}
20
21VarSizeStackTrace::~VarSizeStackTrace() {
22 ResizeBuffer(0);
23}
24
25void 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;
34 trace = trace_buffer;
35 size = new_size;
36}
37
38void VarSizeStackTrace::Init(const uptr *pcs, uptr cnt, uptr extra_top_pc) {
39 ResizeBuffer(cnt + !!extra_top_pc);
40 internal_memcpy(trace_buffer, pcs, cnt * sizeof(trace_buffer[0]));
41 if (extra_top_pc)
42 trace_buffer[cnt] = extra_top_pc;
43}
44
45void VarSizeStackTrace::ReverseOrder() {
46 for (u32 i = 0; i < (size >> 1); i++)
47 Swap(trace_buffer[i], trace_buffer[size - 1 - i]);
48}
49
50} // namespace __tsan
51
52#if !SANITIZER_GO
53void __sanitizer::BufferedStackTrace::UnwindImpl(
54 uptr pc, uptr bp, void *context, bool request_fast, u32 max_depth) {
55 uptr top = 0;
56 uptr bottom = 0;
57 if (StackTrace::WillUseFastUnwind(request_fast)) {
58 GetThreadStackTopAndBottom(false, &top, &bottom);
59 Unwind(max_depth, pc, bp, nullptr, top, bottom, true);
60 } else
61 Unwind(max_depth, pc, 0, context, 0, 0, false);
62}
63#endif // SANITIZER_GO
lib/tsan/tsan_stack_trace.h created+42
...@@ -0,0 +1,42 @@
1//===-- tsan_stack_trace.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_STACK_TRACE_H
13#define TSAN_STACK_TRACE_H
14
15#include "sanitizer_common/sanitizer_stacktrace.h"
16#include "tsan_defs.h"
17
18namespace __tsan {
19
20// StackTrace which calls malloc/free to allocate the buffer for
21// addresses in stack traces.
22struct VarSizeStackTrace : public StackTrace {
23 uptr *trace_buffer; // Owned.
24
25 VarSizeStackTrace();
26 ~VarSizeStackTrace();
27 void Init(const uptr *pcs, uptr cnt, uptr extra_top_pc = 0);
28
29 // Reverses the current stack trace order, the top frame goes to the bottom,
30 // the last frame goes to the top.
31 void ReverseOrder();
32
33 private:
34 void ResizeBuffer(uptr new_size);
35
36 VarSizeStackTrace(const VarSizeStackTrace &);
37 void operator=(const VarSizeStackTrace &);
38};
39
40} // namespace __tsan
41
42#endif // TSAN_STACK_TRACE_H
lib/tsan/tsan_stat.cpp created+186
...@@ -0,0 +1,186 @@
1//===-- tsan_stat.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_stat.h"
13#include "tsan_rtl.h"
14
15namespace __tsan {
16
17#if TSAN_COLLECT_STATS
18
19void StatAggregate(u64 *dst, u64 *src) {
20 for (int i = 0; i < StatCnt; i++)
21 dst[i] += src[i];
22}
23
24void StatOutput(u64 *stat) {
25 stat[StatShadowNonZero] = stat[StatShadowProcessed] - stat[StatShadowZero];
26
27 static const char *name[StatCnt] = {};
28 name[StatMop] = "Memory accesses ";
29 name[StatMopRead] = " Including reads ";
30 name[StatMopWrite] = " writes ";
31 name[StatMop1] = " Including size 1 ";
32 name[StatMop2] = " size 2 ";
33 name[StatMop4] = " size 4 ";
34 name[StatMop8] = " size 8 ";
35 name[StatMopSame] = " Including same ";
36 name[StatMopIgnored] = " Including ignored ";
37 name[StatMopRange] = " Including range ";
38 name[StatMopRodata] = " Including .rodata ";
39 name[StatMopRangeRodata] = " Including .rodata range ";
40 name[StatShadowProcessed] = "Shadow processed ";
41 name[StatShadowZero] = " Including empty ";
42 name[StatShadowNonZero] = " Including non empty ";
43 name[StatShadowSameSize] = " Including same size ";
44 name[StatShadowIntersect] = " intersect ";
45 name[StatShadowNotIntersect] = " not intersect ";
46 name[StatShadowSameThread] = " Including same thread ";
47 name[StatShadowAnotherThread] = " another thread ";
48 name[StatShadowReplace] = " Including evicted ";
49
50 name[StatFuncEnter] = "Function entries ";
51 name[StatFuncExit] = "Function exits ";
52 name[StatEvents] = "Events collected ";
53
54 name[StatThreadCreate] = "Total threads created ";
55 name[StatThreadFinish] = " threads finished ";
56 name[StatThreadReuse] = " threads reused ";
57 name[StatThreadMaxTid] = " max tid ";
58 name[StatThreadMaxAlive] = " max alive threads ";
59
60 name[StatMutexCreate] = "Mutexes created ";
61 name[StatMutexDestroy] = " destroyed ";
62 name[StatMutexLock] = " lock ";
63 name[StatMutexUnlock] = " unlock ";
64 name[StatMutexRecLock] = " recursive lock ";
65 name[StatMutexRecUnlock] = " recursive unlock ";
66 name[StatMutexReadLock] = " read lock ";
67 name[StatMutexReadUnlock] = " read unlock ";
68
69 name[StatSyncCreated] = "Sync objects created ";
70 name[StatSyncDestroyed] = " destroyed ";
71 name[StatSyncAcquire] = " acquired ";
72 name[StatSyncRelease] = " released ";
73
74 name[StatClockAcquire] = "Clock acquire ";
75 name[StatClockAcquireEmpty] = " empty clock ";
76 name[StatClockAcquireFastRelease] = " fast from release-store ";
77 name[StatClockAcquireFull] = " full (slow) ";
78 name[StatClockAcquiredSomething] = " acquired something ";
79 name[StatClockRelease] = "Clock release ";
80 name[StatClockReleaseResize] = " resize ";
81 name[StatClockReleaseFast] = " fast ";
82 name[StatClockReleaseSlow] = " dirty overflow (slow) ";
83 name[StatClockReleaseFull] = " full (slow) ";
84 name[StatClockReleaseAcquired] = " was acquired ";
85 name[StatClockReleaseClearTail] = " clear tail ";
86 name[StatClockStore] = "Clock release store ";
87 name[StatClockStoreResize] = " resize ";
88 name[StatClockStoreFast] = " fast ";
89 name[StatClockStoreFull] = " slow ";
90 name[StatClockStoreTail] = " clear tail ";
91 name[StatClockAcquireRelease] = "Clock acquire-release ";
92
93 name[StatAtomic] = "Atomic operations ";
94 name[StatAtomicLoad] = " Including load ";
95 name[StatAtomicStore] = " store ";
96 name[StatAtomicExchange] = " exchange ";
97 name[StatAtomicFetchAdd] = " fetch_add ";
98 name[StatAtomicFetchSub] = " fetch_sub ";
99 name[StatAtomicFetchAnd] = " fetch_and ";
100 name[StatAtomicFetchOr] = " fetch_or ";
101 name[StatAtomicFetchXor] = " fetch_xor ";
102 name[StatAtomicFetchNand] = " fetch_nand ";
103 name[StatAtomicCAS] = " compare_exchange ";
104 name[StatAtomicFence] = " fence ";
105 name[StatAtomicRelaxed] = " Including relaxed ";
106 name[StatAtomicConsume] = " consume ";
107 name[StatAtomicAcquire] = " acquire ";
108 name[StatAtomicRelease] = " release ";
109 name[StatAtomicAcq_Rel] = " acq_rel ";
110 name[StatAtomicSeq_Cst] = " seq_cst ";
111 name[StatAtomic1] = " Including size 1 ";
112 name[StatAtomic2] = " size 2 ";
113 name[StatAtomic4] = " size 4 ";
114 name[StatAtomic8] = " size 8 ";
115 name[StatAtomic16] = " size 16 ";
116
117 name[StatAnnotation] = "Dynamic annotations ";
118 name[StatAnnotateHappensBefore] = " HappensBefore ";
119 name[StatAnnotateHappensAfter] = " HappensAfter ";
120 name[StatAnnotateCondVarSignal] = " CondVarSignal ";
121 name[StatAnnotateCondVarSignalAll] = " CondVarSignalAll ";
122 name[StatAnnotateMutexIsNotPHB] = " MutexIsNotPHB ";
123 name[StatAnnotateCondVarWait] = " CondVarWait ";
124 name[StatAnnotateRWLockCreate] = " RWLockCreate ";
125 name[StatAnnotateRWLockCreateStatic] = " StatAnnotateRWLockCreateStatic ";
126 name[StatAnnotateRWLockDestroy] = " RWLockDestroy ";
127 name[StatAnnotateRWLockAcquired] = " RWLockAcquired ";
128 name[StatAnnotateRWLockReleased] = " RWLockReleased ";
129 name[StatAnnotateTraceMemory] = " TraceMemory ";
130 name[StatAnnotateFlushState] = " FlushState ";
131 name[StatAnnotateNewMemory] = " NewMemory ";
132 name[StatAnnotateNoOp] = " NoOp ";
133 name[StatAnnotateFlushExpectedRaces] = " FlushExpectedRaces ";
134 name[StatAnnotateEnableRaceDetection] = " EnableRaceDetection ";
135 name[StatAnnotateMutexIsUsedAsCondVar] = " MutexIsUsedAsCondVar ";
136 name[StatAnnotatePCQGet] = " PCQGet ";
137 name[StatAnnotatePCQPut] = " PCQPut ";
138 name[StatAnnotatePCQDestroy] = " PCQDestroy ";
139 name[StatAnnotatePCQCreate] = " PCQCreate ";
140 name[StatAnnotateExpectRace] = " ExpectRace ";
141 name[StatAnnotateBenignRaceSized] = " BenignRaceSized ";
142 name[StatAnnotateBenignRace] = " BenignRace ";
143 name[StatAnnotateIgnoreReadsBegin] = " IgnoreReadsBegin ";
144 name[StatAnnotateIgnoreReadsEnd] = " IgnoreReadsEnd ";
145 name[StatAnnotateIgnoreWritesBegin] = " IgnoreWritesBegin ";
146 name[StatAnnotateIgnoreWritesEnd] = " IgnoreWritesEnd ";
147 name[StatAnnotateIgnoreSyncBegin] = " IgnoreSyncBegin ";
148 name[StatAnnotateIgnoreSyncEnd] = " IgnoreSyncEnd ";
149 name[StatAnnotatePublishMemoryRange] = " PublishMemoryRange ";
150 name[StatAnnotateUnpublishMemoryRange] = " UnpublishMemoryRange ";
151 name[StatAnnotateThreadName] = " ThreadName ";
152 name[Stat__tsan_mutex_create] = " __tsan_mutex_create ";
153 name[Stat__tsan_mutex_destroy] = " __tsan_mutex_destroy ";
154 name[Stat__tsan_mutex_pre_lock] = " __tsan_mutex_pre_lock ";
155 name[Stat__tsan_mutex_post_lock] = " __tsan_mutex_post_lock ";
156 name[Stat__tsan_mutex_pre_unlock] = " __tsan_mutex_pre_unlock ";
157 name[Stat__tsan_mutex_post_unlock] = " __tsan_mutex_post_unlock ";
158 name[Stat__tsan_mutex_pre_signal] = " __tsan_mutex_pre_signal ";
159 name[Stat__tsan_mutex_post_signal] = " __tsan_mutex_post_signal ";
160 name[Stat__tsan_mutex_pre_divert] = " __tsan_mutex_pre_divert ";
161 name[Stat__tsan_mutex_post_divert] = " __tsan_mutex_post_divert ";
162
163 name[StatMtxTotal] = "Contentionz ";
164 name[StatMtxTrace] = " Trace ";
165 name[StatMtxThreads] = " Threads ";
166 name[StatMtxReport] = " Report ";
167 name[StatMtxSyncVar] = " SyncVar ";
168 name[StatMtxSyncTab] = " SyncTab ";
169 name[StatMtxSlab] = " Slab ";
170 name[StatMtxAtExit] = " Atexit ";
171 name[StatMtxAnnotations] = " Annotations ";
172 name[StatMtxMBlock] = " MBlock ";
173 name[StatMtxDeadlockDetector] = " DeadlockDetector ";
174 name[StatMtxFired] = " FiredSuppressions ";
175 name[StatMtxRacy] = " RacyStacks ";
176 name[StatMtxFD] = " FD ";
177 name[StatMtxGlobalProc] = " GlobalProc ";
178
179 Printf("Statistics:\n");
180 for (int i = 0; i < StatCnt; i++)
181 Printf("%s: %16zu\n", name[i], (uptr)stat[i]);
182}
183
184#endif
185
186} // namespace __tsan
lib/tsan/tsan_stat.h created+191
...@@ -0,0 +1,191 @@
1//===-- tsan_stat.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#ifndef TSAN_STAT_H
14#define TSAN_STAT_H
15
16namespace __tsan {
17
18enum StatType {
19 // Memory access processing related stuff.
20 StatMop,
21 StatMopRead,
22 StatMopWrite,
23 StatMop1, // These must be consequtive.
24 StatMop2,
25 StatMop4,
26 StatMop8,
27 StatMopSame,
28 StatMopIgnored,
29 StatMopRange,
30 StatMopRodata,
31 StatMopRangeRodata,
32 StatShadowProcessed,
33 StatShadowZero,
34 StatShadowNonZero, // Derived.
35 StatShadowSameSize,
36 StatShadowIntersect,
37 StatShadowNotIntersect,
38 StatShadowSameThread,
39 StatShadowAnotherThread,
40 StatShadowReplace,
41
42 // Func processing.
43 StatFuncEnter,
44 StatFuncExit,
45
46 // Trace processing.
47 StatEvents,
48
49 // Threads.
50 StatThreadCreate,
51 StatThreadFinish,
52 StatThreadReuse,
53 StatThreadMaxTid,
54 StatThreadMaxAlive,
55
56 // Mutexes.
57 StatMutexCreate,
58 StatMutexDestroy,
59 StatMutexLock,
60 StatMutexUnlock,
61 StatMutexRecLock,
62 StatMutexRecUnlock,
63 StatMutexReadLock,
64 StatMutexReadUnlock,
65
66 // Synchronization.
67 StatSyncCreated,
68 StatSyncDestroyed,
69 StatSyncAcquire,
70 StatSyncRelease,
71 StatSyncReleaseStoreAcquire,
72
73 // Clocks - acquire.
74 StatClockAcquire,
75 StatClockAcquireEmpty,
76 StatClockAcquireFastRelease,
77 StatClockAcquireFull,
78 StatClockAcquiredSomething,
79 // Clocks - release.
80 StatClockRelease,
81 StatClockReleaseResize,
82 StatClockReleaseFast,
83 StatClockReleaseSlow,
84 StatClockReleaseFull,
85 StatClockReleaseAcquired,
86 StatClockReleaseClearTail,
87 // Clocks - release store.
88 StatClockStore,
89 StatClockStoreResize,
90 StatClockStoreFast,
91 StatClockStoreFull,
92 StatClockStoreTail,
93 // Clocks - acquire-release.
94 StatClockAcquireRelease,
95
96 // Atomics.
97 StatAtomic,
98 StatAtomicLoad,
99 StatAtomicStore,
100 StatAtomicExchange,
101 StatAtomicFetchAdd,
102 StatAtomicFetchSub,
103 StatAtomicFetchAnd,
104 StatAtomicFetchOr,
105 StatAtomicFetchXor,
106 StatAtomicFetchNand,
107 StatAtomicCAS,
108 StatAtomicFence,
109 StatAtomicRelaxed,
110 StatAtomicConsume,
111 StatAtomicAcquire,
112 StatAtomicRelease,
113 StatAtomicAcq_Rel,
114 StatAtomicSeq_Cst,
115 StatAtomic1,
116 StatAtomic2,
117 StatAtomic4,
118 StatAtomic8,
119 StatAtomic16,
120
121 // Dynamic annotations.
122 StatAnnotation,
123 StatAnnotateHappensBefore,
124 StatAnnotateHappensAfter,
125 StatAnnotateCondVarSignal,
126 StatAnnotateCondVarSignalAll,
127 StatAnnotateMutexIsNotPHB,
128 StatAnnotateCondVarWait,
129 StatAnnotateRWLockCreate,
130 StatAnnotateRWLockCreateStatic,
131 StatAnnotateRWLockDestroy,
132 StatAnnotateRWLockAcquired,
133 StatAnnotateRWLockReleased,
134 StatAnnotateTraceMemory,
135 StatAnnotateFlushState,
136 StatAnnotateNewMemory,
137 StatAnnotateNoOp,
138 StatAnnotateFlushExpectedRaces,
139 StatAnnotateEnableRaceDetection,
140 StatAnnotateMutexIsUsedAsCondVar,
141 StatAnnotatePCQGet,
142 StatAnnotatePCQPut,
143 StatAnnotatePCQDestroy,
144 StatAnnotatePCQCreate,
145 StatAnnotateExpectRace,
146 StatAnnotateBenignRaceSized,
147 StatAnnotateBenignRace,
148 StatAnnotateIgnoreReadsBegin,
149 StatAnnotateIgnoreReadsEnd,
150 StatAnnotateIgnoreWritesBegin,
151 StatAnnotateIgnoreWritesEnd,
152 StatAnnotateIgnoreSyncBegin,
153 StatAnnotateIgnoreSyncEnd,
154 StatAnnotatePublishMemoryRange,
155 StatAnnotateUnpublishMemoryRange,
156 StatAnnotateThreadName,
157 Stat__tsan_mutex_create,
158 Stat__tsan_mutex_destroy,
159 Stat__tsan_mutex_pre_lock,
160 Stat__tsan_mutex_post_lock,
161 Stat__tsan_mutex_pre_unlock,
162 Stat__tsan_mutex_post_unlock,
163 Stat__tsan_mutex_pre_signal,
164 Stat__tsan_mutex_post_signal,
165 Stat__tsan_mutex_pre_divert,
166 Stat__tsan_mutex_post_divert,
167
168 // Internal mutex contentionz.
169 StatMtxTotal,
170 StatMtxTrace,
171 StatMtxThreads,
172 StatMtxReport,
173 StatMtxSyncVar,
174 StatMtxSyncTab,
175 StatMtxSlab,
176 StatMtxAnnotations,
177 StatMtxAtExit,
178 StatMtxMBlock,
179 StatMtxDeadlockDetector,
180 StatMtxFired,
181 StatMtxRacy,
182 StatMtxFD,
183 StatMtxGlobalProc,
184
185 // This must be the last.
186 StatCnt
187};
188
189} // namespace __tsan
190
191#endif // TSAN_STAT_H
lib/tsan/tsan_suppressions.cpp created+161
...@@ -0,0 +1,161 @@
1//===-- tsan_suppressions.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#include "sanitizer_common/sanitizer_common.h"
14#include "sanitizer_common/sanitizer_libc.h"
15#include "sanitizer_common/sanitizer_placement_new.h"
16#include "sanitizer_common/sanitizer_suppressions.h"
17#include "tsan_suppressions.h"
18#include "tsan_rtl.h"
19#include "tsan_flags.h"
20#include "tsan_mman.h"
21#include "tsan_platform.h"
22
23#if !SANITIZER_GO
24// Suppressions for true/false positives in standard libraries.
25static const char *const std_suppressions =
26// Libstdc++ 4.4 has data races in std::string.
27// See http://crbug.com/181502 for an example.
28"race:^_M_rep$\n"
29"race:^_M_is_leaked$\n"
30// False positive when using std <thread>.
31// Happens because we miss atomic synchronization in libstdc++.
32// See http://llvm.org/bugs/show_bug.cgi?id=17066 for details.
33"race:std::_Sp_counted_ptr_inplace<std::thread::_Impl\n";
34
35// Can be overriden in frontend.
36SANITIZER_WEAK_DEFAULT_IMPL
37const char *__tsan_default_suppressions() {
38 return 0;
39}
40#endif
41
42namespace __tsan {
43
44ALIGNED(64) static char suppression_placeholder[sizeof(SuppressionContext)];
45static SuppressionContext *suppression_ctx = nullptr;
46static const char *kSuppressionTypes[] = {
47 kSuppressionRace, kSuppressionRaceTop, kSuppressionMutex,
48 kSuppressionThread, kSuppressionSignal, kSuppressionLib,
49 kSuppressionDeadlock};
50
51void InitializeSuppressions() {
52 CHECK_EQ(nullptr, suppression_ctx);
53 suppression_ctx = new (suppression_placeholder)
54 SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes));
55 suppression_ctx->ParseFromFile(flags()->suppressions);
56#if !SANITIZER_GO
57 suppression_ctx->Parse(__tsan_default_suppressions());
58 suppression_ctx->Parse(std_suppressions);
59#endif
60}
61
62SuppressionContext *Suppressions() {
63 CHECK(suppression_ctx);
64 return suppression_ctx;
65}
66
67static const char *conv(ReportType typ) {
68 switch (typ) {
69 case ReportTypeRace:
70 case ReportTypeVptrRace:
71 case ReportTypeUseAfterFree:
72 case ReportTypeVptrUseAfterFree:
73 case ReportTypeExternalRace:
74 return kSuppressionRace;
75 case ReportTypeThreadLeak:
76 return kSuppressionThread;
77 case ReportTypeMutexDestroyLocked:
78 case ReportTypeMutexDoubleLock:
79 case ReportTypeMutexInvalidAccess:
80 case ReportTypeMutexBadUnlock:
81 case ReportTypeMutexBadReadLock:
82 case ReportTypeMutexBadReadUnlock:
83 return kSuppressionMutex;
84 case ReportTypeSignalUnsafe:
85 case ReportTypeErrnoInSignal:
86 return kSuppressionSignal;
87 case ReportTypeDeadlock:
88 return kSuppressionDeadlock;
89 // No default case so compiler warns us if we miss one
90 }
91 UNREACHABLE("missing case");
92}
93
94static uptr IsSuppressed(const char *stype, const AddressInfo &info,
95 Suppression **sp) {
96 if (suppression_ctx->Match(info.function, stype, sp) ||
97 suppression_ctx->Match(info.file, stype, sp) ||
98 suppression_ctx->Match(info.module, stype, sp)) {
99 VPrintf(2, "ThreadSanitizer: matched suppression '%s'\n", (*sp)->templ);
100 atomic_fetch_add(&(*sp)->hit_count, 1, memory_order_relaxed);
101 return info.address;
102 }
103 return 0;
104}
105
106uptr IsSuppressed(ReportType typ, const ReportStack *stack, Suppression **sp) {
107 CHECK(suppression_ctx);
108 if (!suppression_ctx->SuppressionCount() || stack == 0 ||
109 !stack->suppressable)
110 return 0;
111 const char *stype = conv(typ);
112 if (0 == internal_strcmp(stype, kSuppressionNone))
113 return 0;
114 for (const SymbolizedStack *frame = stack->frames; frame;
115 frame = frame->next) {
116 uptr pc = IsSuppressed(stype, frame->info, sp);
117 if (pc != 0)
118 return pc;
119 }
120 if (0 == internal_strcmp(stype, kSuppressionRace) && stack->frames != nullptr)
121 return IsSuppressed(kSuppressionRaceTop, stack->frames->info, sp);
122 return 0;
123}
124
125uptr IsSuppressed(ReportType typ, const ReportLocation *loc, Suppression **sp) {
126 CHECK(suppression_ctx);
127 if (!suppression_ctx->SuppressionCount() || loc == 0 ||
128 loc->type != ReportLocationGlobal || !loc->suppressable)
129 return 0;
130 const char *stype = conv(typ);
131 if (0 == internal_strcmp(stype, kSuppressionNone))
132 return 0;
133 Suppression *s;
134 const DataInfo &global = loc->global;
135 if (suppression_ctx->Match(global.name, stype, &s) ||
136 suppression_ctx->Match(global.module, stype, &s)) {
137 VPrintf(2, "ThreadSanitizer: matched suppression '%s'\n", s->templ);
138 atomic_fetch_add(&s->hit_count, 1, memory_order_relaxed);
139 *sp = s;
140 return global.start;
141 }
142 return 0;
143}
144
145void PrintMatchedSuppressions() {
146 InternalMmapVector<Suppression *> matched;
147 CHECK(suppression_ctx);
148 suppression_ctx->GetMatched(&matched);
149 if (!matched.size())
150 return;
151 int hit_count = 0;
152 for (uptr i = 0; i < matched.size(); i++)
153 hit_count += atomic_load_relaxed(&matched[i]->hit_count);
154 Printf("ThreadSanitizer: Matched %d suppressions (pid=%d):\n", hit_count,
155 (int)internal_getpid());
156 for (uptr i = 0; i < matched.size(); i++) {
157 Printf("%d %s:%s\n", atomic_load_relaxed(&matched[i]->hit_count),
158 matched[i]->type, matched[i]->templ);
159 }
160}
161} // namespace __tsan
lib/tsan/tsan_suppressions.h created+37
...@@ -0,0 +1,37 @@
1//===-- tsan_suppressions.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_SUPPRESSIONS_H
13#define TSAN_SUPPRESSIONS_H
14
15#include "sanitizer_common/sanitizer_suppressions.h"
16#include "tsan_report.h"
17
18namespace __tsan {
19
20const char kSuppressionNone[] = "none";
21const char kSuppressionRace[] = "race";
22const char kSuppressionRaceTop[] = "race_top";
23const char kSuppressionMutex[] = "mutex";
24const char kSuppressionThread[] = "thread";
25const char kSuppressionSignal[] = "signal";
26const char kSuppressionLib[] = "called_from_lib";
27const char kSuppressionDeadlock[] = "deadlock";
28
29void InitializeSuppressions();
30SuppressionContext *Suppressions();
31void PrintMatchedSuppressions();
32uptr IsSuppressed(ReportType typ, const ReportStack *stack, Suppression **sp);
33uptr IsSuppressed(ReportType typ, const ReportLocation *loc, Suppression **sp);
34
35} // namespace __tsan
36
37#endif // TSAN_SUPPRESSIONS_H
lib/tsan/tsan_symbolize.cpp created+122
...@@ -0,0 +1,122 @@
1//===-- tsan_symbolize.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#include "tsan_symbolize.h"
14
15#include "sanitizer_common/sanitizer_common.h"
16#include "sanitizer_common/sanitizer_placement_new.h"
17#include "sanitizer_common/sanitizer_symbolizer.h"
18#include "tsan_flags.h"
19#include "tsan_report.h"
20#include "tsan_rtl.h"
21
22namespace __tsan {
23
24void EnterSymbolizer() {
25 ThreadState *thr = cur_thread();
26 CHECK(!thr->in_symbolizer);
27 thr->in_symbolizer = true;
28 thr->ignore_interceptors++;
29}
30
31void ExitSymbolizer() {
32 ThreadState *thr = cur_thread();
33 CHECK(thr->in_symbolizer);
34 thr->in_symbolizer = false;
35 thr->ignore_interceptors--;
36}
37
38// Legacy API.
39// May be overriden by JIT/JAVA/etc,
40// whatever produces PCs marked with kExternalPCBit.
41SANITIZER_WEAK_DEFAULT_IMPL
42bool __tsan_symbolize_external(uptr pc, char *func_buf, uptr func_siz,
43 char *file_buf, uptr file_siz, int *line,
44 int *col) {
45 return false;
46}
47
48// New API: call __tsan_symbolize_external_ex only when it exists.
49// Once old clients are gone, provide dummy implementation.
50SANITIZER_WEAK_DEFAULT_IMPL
51void __tsan_symbolize_external_ex(uptr pc,
52 void (*add_frame)(void *, const char *,
53 const char *, int, int),
54 void *ctx) {}
55
56struct SymbolizedStackBuilder {
57 SymbolizedStack *head;
58 SymbolizedStack *tail;
59 uptr addr;
60};
61
62static void AddFrame(void *ctx, const char *function_name, const char *file,
63 int line, int column) {
64 SymbolizedStackBuilder *ssb = (struct SymbolizedStackBuilder *)ctx;
65 if (ssb->tail) {
66 ssb->tail->next = SymbolizedStack::New(ssb->addr);
67 ssb->tail = ssb->tail->next;
68 } else {
69 ssb->head = ssb->tail = SymbolizedStack::New(ssb->addr);
70 }
71 AddressInfo *info = &ssb->tail->info;
72 if (function_name) {
73 info->function = internal_strdup(function_name);
74 }
75 if (file) {
76 info->file = internal_strdup(file);
77 }
78 info->line = line;
79 info->column = column;
80}
81
82SymbolizedStack *SymbolizeCode(uptr addr) {
83 // Check if PC comes from non-native land.
84 if (addr & kExternalPCBit) {
85 SymbolizedStackBuilder ssb = {nullptr, nullptr, addr};
86 __tsan_symbolize_external_ex(addr, AddFrame, &ssb);
87 if (ssb.head)
88 return ssb.head;
89 // Legacy code: remove along with the declaration above
90 // once all clients using this API are gone.
91 // Declare static to not consume too much stack space.
92 // We symbolize reports in a single thread, so this is fine.
93 static char func_buf[1024];
94 static char file_buf[1024];
95 int line, col;
96 SymbolizedStack *frame = SymbolizedStack::New(addr);
97 if (__tsan_symbolize_external(addr, func_buf, sizeof(func_buf), file_buf,
98 sizeof(file_buf), &line, &col)) {
99 frame->info.function = internal_strdup(func_buf);
100 frame->info.file = internal_strdup(file_buf);
101 frame->info.line = line;
102 frame->info.column = col;
103 }
104 return frame;
105 }
106 return Symbolizer::GetOrInit()->SymbolizePC(addr);
107}
108
109ReportLocation *SymbolizeData(uptr addr) {
110 DataInfo info;
111 if (!Symbolizer::GetOrInit()->SymbolizeData(addr, &info))
112 return 0;
113 ReportLocation *ent = ReportLocation::New(ReportLocationGlobal);
114 internal_memcpy(&ent->global, &info, sizeof(info));
115 return ent;
116}
117
118void SymbolizeFlush() {
119 Symbolizer::GetOrInit()->Flush();
120}
121
122} // namespace __tsan
lib/tsan/tsan_symbolize.h created+30
...@@ -0,0 +1,30 @@
1//===-- tsan_symbolize.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_SYMBOLIZE_H
13#define TSAN_SYMBOLIZE_H
14
15#include "tsan_defs.h"
16#include "tsan_report.h"
17
18namespace __tsan {
19
20void EnterSymbolizer();
21void ExitSymbolizer();
22SymbolizedStack *SymbolizeCode(uptr addr);
23ReportLocation *SymbolizeData(uptr addr);
24void SymbolizeFlush();
25
26ReportStack *NewReportStackEntry(uptr addr);
27
28} // namespace __tsan
29
30#endif // TSAN_SYMBOLIZE_H
lib/tsan/tsan_sync.cpp created+296
...@@ -0,0 +1,296 @@
1//===-- tsan_sync.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 "sanitizer_common/sanitizer_placement_new.h"
13#include "tsan_sync.h"
14#include "tsan_rtl.h"
15#include "tsan_mman.h"
16
17namespace __tsan {
18
19void DDMutexInit(ThreadState *thr, uptr pc, SyncVar *s);
20
21SyncVar::SyncVar()
22 : mtx(MutexTypeSyncVar, StatMtxSyncVar) {
23 Reset(0);
24}
25
26void SyncVar::Init(ThreadState *thr, uptr pc, uptr addr, u64 uid) {
27 this->addr = addr;
28 this->uid = uid;
29 this->next = 0;
30
31 creation_stack_id = 0;
32 if (!SANITIZER_GO) // Go does not use them
33 creation_stack_id = CurrentStackId(thr, pc);
34 if (common_flags()->detect_deadlocks)
35 DDMutexInit(thr, pc, this);
36}
37
38void SyncVar::Reset(Processor *proc) {
39 uid = 0;
40 creation_stack_id = 0;
41 owner_tid = kInvalidTid;
42 last_lock = 0;
43 recursion = 0;
44 atomic_store_relaxed(&flags, 0);
45
46 if (proc == 0) {
47 CHECK_EQ(clock.size(), 0);
48 CHECK_EQ(read_clock.size(), 0);
49 } else {
50 clock.Reset(&proc->clock_cache);
51 read_clock.Reset(&proc->clock_cache);
52 }
53}
54
55MetaMap::MetaMap()
56 : block_alloc_("heap block allocator")
57 , sync_alloc_("sync allocator") {
58 atomic_store(&uid_gen_, 0, memory_order_relaxed);
59}
60
61void MetaMap::AllocBlock(ThreadState *thr, uptr pc, uptr p, uptr sz) {
62 u32 idx = block_alloc_.Alloc(&thr->proc()->block_cache);
63 MBlock *b = block_alloc_.Map(idx);
64 b->siz = sz;
65 b->tag = 0;
66 b->tid = thr->tid;
67 b->stk = CurrentStackId(thr, pc);
68 u32 *meta = MemToMeta(p);
69 DCHECK_EQ(*meta, 0);
70 *meta = idx | kFlagBlock;
71}
72
73uptr MetaMap::FreeBlock(Processor *proc, uptr p) {
74 MBlock* b = GetBlock(p);
75 if (b == 0)
76 return 0;
77 uptr sz = RoundUpTo(b->siz, kMetaShadowCell);
78 FreeRange(proc, p, sz);
79 return sz;
80}
81
82bool MetaMap::FreeRange(Processor *proc, uptr p, uptr sz) {
83 bool has_something = false;
84 u32 *meta = MemToMeta(p);
85 u32 *end = MemToMeta(p + sz);
86 if (end == meta)
87 end++;
88 for (; meta < end; meta++) {
89 u32 idx = *meta;
90 if (idx == 0) {
91 // Note: don't write to meta in this case -- the block can be huge.
92 continue;
93 }
94 *meta = 0;
95 has_something = true;
96 while (idx != 0) {
97 if (idx & kFlagBlock) {
98 block_alloc_.Free(&proc->block_cache, idx & ~kFlagMask);
99 break;
100 } else if (idx & kFlagSync) {
101 DCHECK(idx & kFlagSync);
102 SyncVar *s = sync_alloc_.Map(idx & ~kFlagMask);
103 u32 next = s->next;
104 s->Reset(proc);
105 sync_alloc_.Free(&proc->sync_cache, idx & ~kFlagMask);
106 idx = next;
107 } else {
108 CHECK(0);
109 }
110 }
111 }
112 return has_something;
113}
114
115// ResetRange removes all meta objects from the range.
116// It is called for large mmap-ed regions. The function is best-effort wrt
117// freeing of meta objects, because we don't want to page in the whole range
118// which can be huge. The function probes pages one-by-one until it finds a page
119// without meta objects, at this point it stops freeing meta objects. Because
120// thread stacks grow top-down, we do the same starting from end as well.
121void MetaMap::ResetRange(Processor *proc, uptr p, uptr sz) {
122 if (SANITIZER_GO) {
123 // UnmapOrDie/MmapFixedNoReserve does not work on Windows,
124 // so we do the optimization only for C/C++.
125 FreeRange(proc, p, sz);
126 return;
127 }
128 const uptr kMetaRatio = kMetaShadowCell / kMetaShadowSize;
129 const uptr kPageSize = GetPageSizeCached() * kMetaRatio;
130 if (sz <= 4 * kPageSize) {
131 // If the range is small, just do the normal free procedure.
132 FreeRange(proc, p, sz);
133 return;
134 }
135 // First, round both ends of the range to page size.
136 uptr diff = RoundUp(p, kPageSize) - p;
137 if (diff != 0) {
138 FreeRange(proc, p, diff);
139 p += diff;
140 sz -= diff;
141 }
142 diff = p + sz - RoundDown(p + sz, kPageSize);
143 if (diff != 0) {
144 FreeRange(proc, p + sz - diff, diff);
145 sz -= diff;
146 }
147 // Now we must have a non-empty page-aligned range.
148 CHECK_GT(sz, 0);
149 CHECK_EQ(p, RoundUp(p, kPageSize));
150 CHECK_EQ(sz, RoundUp(sz, kPageSize));
151 const uptr p0 = p;
152 const uptr sz0 = sz;
153 // Probe start of the range.
154 for (uptr checked = 0; sz > 0; checked += kPageSize) {
155 bool has_something = FreeRange(proc, p, kPageSize);
156 p += kPageSize;
157 sz -= kPageSize;
158 if (!has_something && checked > (128 << 10))
159 break;
160 }
161 // Probe end of the range.
162 for (uptr checked = 0; sz > 0; checked += kPageSize) {
163 bool has_something = FreeRange(proc, p + sz - kPageSize, kPageSize);
164 sz -= kPageSize;
165 // Stacks grow down, so sync object are most likely at the end of the region
166 // (if it is a stack). The very end of the stack is TLS and tsan increases
167 // TLS by at least 256K, so check at least 512K.
168 if (!has_something && checked > (512 << 10))
169 break;
170 }
171 // Finally, page out the whole range (including the parts that we've just
172 // freed). Note: we can't simply madvise, because we need to leave a zeroed
173 // range (otherwise __tsan_java_move can crash if it encounters a left-over
174 // meta objects in java heap).
175 uptr metap = (uptr)MemToMeta(p0);
176 uptr metasz = sz0 / kMetaRatio;
177 UnmapOrDie((void*)metap, metasz);
178 if (!MmapFixedNoReserve(metap, metasz))
179 Die();
180}
181
182MBlock* MetaMap::GetBlock(uptr p) {
183 u32 *meta = MemToMeta(p);
184 u32 idx = *meta;
185 for (;;) {
186 if (idx == 0)
187 return 0;
188 if (idx & kFlagBlock)
189 return block_alloc_.Map(idx & ~kFlagMask);
190 DCHECK(idx & kFlagSync);
191 SyncVar * s = sync_alloc_.Map(idx & ~kFlagMask);
192 idx = s->next;
193 }
194}
195
196SyncVar* MetaMap::GetOrCreateAndLock(ThreadState *thr, uptr pc,
197 uptr addr, bool write_lock) {
198 return GetAndLock(thr, pc, addr, write_lock, true);
199}
200
201SyncVar* MetaMap::GetIfExistsAndLock(uptr addr, bool write_lock) {
202 return GetAndLock(0, 0, addr, write_lock, false);
203}
204
205SyncVar* MetaMap::GetAndLock(ThreadState *thr, uptr pc,
206 uptr addr, bool write_lock, bool create) {
207 u32 *meta = MemToMeta(addr);
208 u32 idx0 = *meta;
209 u32 myidx = 0;
210 SyncVar *mys = 0;
211 for (;;) {
212 u32 idx = idx0;
213 for (;;) {
214 if (idx == 0)
215 break;
216 if (idx & kFlagBlock)
217 break;
218 DCHECK(idx & kFlagSync);
219 SyncVar * s = sync_alloc_.Map(idx & ~kFlagMask);
220 if (s->addr == addr) {
221 if (myidx != 0) {
222 mys->Reset(thr->proc());
223 sync_alloc_.Free(&thr->proc()->sync_cache, myidx);
224 }
225 if (write_lock)
226 s->mtx.Lock();
227 else
228 s->mtx.ReadLock();
229 return s;
230 }
231 idx = s->next;
232 }
233 if (!create)
234 return 0;
235 if (*meta != idx0) {
236 idx0 = *meta;
237 continue;
238 }
239
240 if (myidx == 0) {
241 const u64 uid = atomic_fetch_add(&uid_gen_, 1, memory_order_relaxed);
242 myidx = sync_alloc_.Alloc(&thr->proc()->sync_cache);
243 mys = sync_alloc_.Map(myidx);
244 mys->Init(thr, pc, addr, uid);
245 }
246 mys->next = idx0;
247 if (atomic_compare_exchange_strong((atomic_uint32_t*)meta, &idx0,
248 myidx | kFlagSync, memory_order_release)) {
249 if (write_lock)
250 mys->mtx.Lock();
251 else
252 mys->mtx.ReadLock();
253 return mys;
254 }
255 }
256}
257
258void MetaMap::MoveMemory(uptr src, uptr dst, uptr sz) {
259 // src and dst can overlap,
260 // there are no concurrent accesses to the regions (e.g. stop-the-world).
261 CHECK_NE(src, dst);
262 CHECK_NE(sz, 0);
263 uptr diff = dst - src;
264 u32 *src_meta = MemToMeta(src);
265 u32 *dst_meta = MemToMeta(dst);
266 u32 *src_meta_end = MemToMeta(src + sz);
267 uptr inc = 1;
268 if (dst > src) {
269 src_meta = MemToMeta(src + sz) - 1;
270 dst_meta = MemToMeta(dst + sz) - 1;
271 src_meta_end = MemToMeta(src) - 1;
272 inc = -1;
273 }
274 for (; src_meta != src_meta_end; src_meta += inc, dst_meta += inc) {
275 CHECK_EQ(*dst_meta, 0);
276 u32 idx = *src_meta;
277 *src_meta = 0;
278 *dst_meta = idx;
279 // Patch the addresses in sync objects.
280 while (idx != 0) {
281 if (idx & kFlagBlock)
282 break;
283 CHECK(idx & kFlagSync);
284 SyncVar *s = sync_alloc_.Map(idx & ~kFlagMask);
285 s->addr += diff;
286 idx = s->next;
287 }
288 }
289}
290
291void MetaMap::OnProcIdle(Processor *proc) {
292 block_alloc_.FlushCache(&proc->block_cache);
293 sync_alloc_.FlushCache(&proc->sync_cache);
294}
295
296} // namespace __tsan
lib/tsan/tsan_sync.h created+145
...@@ -0,0 +1,145 @@
1//===-- tsan_sync.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_SYNC_H
13#define TSAN_SYNC_H
14
15#include "sanitizer_common/sanitizer_atomic.h"
16#include "sanitizer_common/sanitizer_common.h"
17#include "sanitizer_common/sanitizer_deadlock_detector_interface.h"
18#include "tsan_defs.h"
19#include "tsan_clock.h"
20#include "tsan_mutex.h"
21#include "tsan_dense_alloc.h"
22
23namespace __tsan {
24
25// These need to match __tsan_mutex_* flags defined in tsan_interface.h.
26// See documentation there as well.
27enum MutexFlags {
28 MutexFlagLinkerInit = 1 << 0, // __tsan_mutex_linker_init
29 MutexFlagWriteReentrant = 1 << 1, // __tsan_mutex_write_reentrant
30 MutexFlagReadReentrant = 1 << 2, // __tsan_mutex_read_reentrant
31 MutexFlagReadLock = 1 << 3, // __tsan_mutex_read_lock
32 MutexFlagTryLock = 1 << 4, // __tsan_mutex_try_lock
33 MutexFlagTryLockFailed = 1 << 5, // __tsan_mutex_try_lock_failed
34 MutexFlagRecursiveLock = 1 << 6, // __tsan_mutex_recursive_lock
35 MutexFlagRecursiveUnlock = 1 << 7, // __tsan_mutex_recursive_unlock
36 MutexFlagNotStatic = 1 << 8, // __tsan_mutex_not_static
37
38 // The following flags are runtime private.
39 // Mutex API misuse was detected, so don't report any more.
40 MutexFlagBroken = 1 << 30,
41 // We did not intercept pre lock event, so handle it on post lock.
42 MutexFlagDoPreLockOnPostLock = 1 << 29,
43 // Must list all mutex creation flags.
44 MutexCreationFlagMask = MutexFlagLinkerInit |
45 MutexFlagWriteReentrant |
46 MutexFlagReadReentrant |
47 MutexFlagNotStatic,
48};
49
50struct SyncVar {
51 SyncVar();
52
53 static const int kInvalidTid = -1;
54
55 uptr addr; // overwritten by DenseSlabAlloc freelist
56 Mutex mtx;
57 u64 uid; // Globally unique id.
58 u32 creation_stack_id;
59 int owner_tid; // Set only by exclusive owners.
60 u64 last_lock;
61 int recursion;
62 atomic_uint32_t flags;
63 u32 next; // in MetaMap
64 DDMutex dd;
65 SyncClock read_clock; // Used for rw mutexes only.
66 // The clock is placed last, so that it is situated on a different cache line
67 // with the mtx. This reduces contention for hot sync objects.
68 SyncClock clock;
69
70 void Init(ThreadState *thr, uptr pc, uptr addr, u64 uid);
71 void Reset(Processor *proc);
72
73 u64 GetId() const {
74 // 48 lsb is addr, then 14 bits is low part of uid, then 2 zero bits.
75 return GetLsb((u64)addr | (uid << 48), 60);
76 }
77 bool CheckId(u64 uid) const {
78 CHECK_EQ(uid, GetLsb(uid, 14));
79 return GetLsb(this->uid, 14) == uid;
80 }
81 static uptr SplitId(u64 id, u64 *uid) {
82 *uid = id >> 48;
83 return (uptr)GetLsb(id, 48);
84 }
85
86 bool IsFlagSet(u32 f) const {
87 return atomic_load_relaxed(&flags) & f;
88 }
89
90 void SetFlags(u32 f) {
91 atomic_store_relaxed(&flags, atomic_load_relaxed(&flags) | f);
92 }
93
94 void UpdateFlags(u32 flagz) {
95 // Filter out operation flags.
96 if (!(flagz & MutexCreationFlagMask))
97 return;
98 u32 current = atomic_load_relaxed(&flags);
99 if (current & MutexCreationFlagMask)
100 return;
101 // Note: this can be called from MutexPostReadLock which holds only read
102 // lock on the SyncVar.
103 atomic_store_relaxed(&flags, current | (flagz & MutexCreationFlagMask));
104 }
105};
106
107/* MetaMap allows to map arbitrary user pointers onto various descriptors.
108 Currently it maps pointers to heap block descriptors and sync var descs.
109 It uses 1/2 direct shadow, see tsan_platform.h.
110*/
111class MetaMap {
112 public:
113 MetaMap();
114
115 void AllocBlock(ThreadState *thr, uptr pc, uptr p, uptr sz);
116 uptr FreeBlock(Processor *proc, uptr p);
117 bool FreeRange(Processor *proc, uptr p, uptr sz);
118 void ResetRange(Processor *proc, uptr p, uptr sz);
119 MBlock* GetBlock(uptr p);
120
121 SyncVar* GetOrCreateAndLock(ThreadState *thr, uptr pc,
122 uptr addr, bool write_lock);
123 SyncVar* GetIfExistsAndLock(uptr addr, bool write_lock);
124
125 void MoveMemory(uptr src, uptr dst, uptr sz);
126
127 void OnProcIdle(Processor *proc);
128
129 private:
130 static const u32 kFlagMask = 3u << 30;
131 static const u32 kFlagBlock = 1u << 30;
132 static const u32 kFlagSync = 2u << 30;
133 typedef DenseSlabAlloc<MBlock, 1<<16, 1<<12> BlockAlloc;
134 typedef DenseSlabAlloc<SyncVar, 1<<16, 1<<10> SyncAlloc;
135 BlockAlloc block_alloc_;
136 SyncAlloc sync_alloc_;
137 atomic_uint64_t uid_gen_;
138
139 SyncVar* GetAndLock(ThreadState *thr, uptr pc, uptr addr, bool write_lock,
140 bool create);
141};
142
143} // namespace __tsan
144
145#endif // TSAN_SYNC_H
lib/tsan/tsan_trace.h created+75
...@@ -0,0 +1,75 @@
1//===-- tsan_trace.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_TRACE_H
13#define TSAN_TRACE_H
14
15#include "tsan_defs.h"
16#include "tsan_mutex.h"
17#include "tsan_stack_trace.h"
18#include "tsan_mutexset.h"
19
20namespace __tsan {
21
22const int kTracePartSizeBits = 13;
23const int kTracePartSize = 1 << kTracePartSizeBits;
24const int kTraceParts = 2 * 1024 * 1024 / kTracePartSize;
25const int kTraceSize = kTracePartSize * kTraceParts;
26
27// Must fit into 3 bits.
28enum EventType {
29 EventTypeMop,
30 EventTypeFuncEnter,
31 EventTypeFuncExit,
32 EventTypeLock,
33 EventTypeUnlock,
34 EventTypeRLock,
35 EventTypeRUnlock
36};
37
38// Represents a thread event (from most significant bit):
39// u64 typ : 3; // EventType.
40// u64 addr : 61; // Associated pc.
41typedef u64 Event;
42
43const uptr kEventPCBits = 61;
44
45struct TraceHeader {
46#if !SANITIZER_GO
47 BufferedStackTrace stack0; // Start stack for the trace.
48#else
49 VarSizeStackTrace stack0;
50#endif
51 u64 epoch0; // Start epoch for the trace.
52 MutexSet mset0;
53
54 TraceHeader() : stack0(), epoch0() {}
55};
56
57struct Trace {
58 Mutex mtx;
59#if !SANITIZER_GO
60 // Must be last to catch overflow as paging fault.
61 // Go shadow stack is dynamically allocated.
62 uptr shadow_stack[kShadowStackSize];
63#endif
64 // Must be the last field, because we unmap the unused part in
65 // CreateThreadContext.
66 TraceHeader headers[kTraceParts];
67
68 Trace()
69 : mtx(MutexTypeTrace, StatMtxTrace) {
70 }
71};
72
73} // namespace __tsan
74
75#endif // TSAN_TRACE_H
lib/tsan/tsan_update_shadow_word_inl.h created+69
...@@ -0,0 +1,69 @@
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 StatInc(thr, StatShadowProcessed);
17 const unsigned kAccessSize = 1 << kAccessSizeLog;
18 u64 *sp = &shadow_mem[idx];
19 old = LoadShadow(sp);
20 if (LIKELY(old.IsZero())) {
21 StatInc(thr, StatShadowZero);
22 if (!stored) {
23 StoreIfNotYetStored(sp, &store_word);
24 stored = true;
25 }
26 break;
27 }
28 // is the memory access equal to the previous?
29 if (LIKELY(Shadow::Addr0AndSizeAreEqual(cur, old))) {
30 StatInc(thr, StatShadowSameSize);
31 // same thread?
32 if (LIKELY(Shadow::TidsAreEqual(old, cur))) {
33 StatInc(thr, StatShadowSameThread);
34 if (LIKELY(old.IsRWWeakerOrEqual(kAccessIsWrite, kIsAtomic))) {
35 StoreIfNotYetStored(sp, &store_word);
36 stored = true;
37 }
38 break;
39 }
40 StatInc(thr, StatShadowAnotherThread);
41 if (HappensBefore(old, thr)) {
42 if (old.IsRWWeakerOrEqual(kAccessIsWrite, kIsAtomic)) {
43 StoreIfNotYetStored(sp, &store_word);
44 stored = true;
45 }
46 break;
47 }
48 if (LIKELY(old.IsBothReadsOrAtomic(kAccessIsWrite, kIsAtomic)))
49 break;
50 goto RACE;
51 }
52 // Do the memory access intersect?
53 if (Shadow::TwoRangesIntersect(old, cur, kAccessSize)) {
54 StatInc(thr, StatShadowIntersect);
55 if (Shadow::TidsAreEqual(old, cur)) {
56 StatInc(thr, StatShadowSameThread);
57 break;
58 }
59 StatInc(thr, StatShadowAnotherThread);
60 if (old.IsBothReadsOrAtomic(kAccessIsWrite, kIsAtomic))
61 break;
62 if (LIKELY(HappensBefore(old, thr)))
63 break;
64 goto RACE;
65 }
66 // The accesses do not intersect.
67 StatInc(thr, StatShadowNotIntersect);
68 break;
69} while (0);
lib/tsan/ubsan/ubsan_flags.h created+48
...@@ -0,0 +1,48 @@
1//===-- ubsan_flags.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// Runtime flags for UndefinedBehaviorSanitizer.
10//
11//===----------------------------------------------------------------------===//
12#ifndef UBSAN_FLAGS_H
13#define UBSAN_FLAGS_H
14
15#include "sanitizer_common/sanitizer_internal_defs.h"
16
17namespace __sanitizer {
18class FlagParser;
19}
20
21namespace __ubsan {
22
23struct Flags {
24#define UBSAN_FLAG(Type, Name, DefaultValue, Description) Type Name;
25#include "ubsan_flags.inc"
26#undef UBSAN_FLAG
27
28 void SetDefaults();
29};
30
31extern Flags ubsan_flags;
32inline Flags *flags() { return &ubsan_flags; }
33
34void InitializeFlags();
35void RegisterUbsanFlags(FlagParser *parser, Flags *f);
36
37const char *MaybeCallUbsanDefaultOptions();
38
39} // namespace __ubsan
40
41extern "C" {
42// Users may provide their own implementation of __ubsan_default_options to
43// override the default flag values.
44SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
45const char *__ubsan_default_options();
46} // extern "C"
47
48#endif // UBSAN_FLAGS_H
lib/tsan/ubsan/ubsan_flags.inc created+28
...@@ -0,0 +1,28 @@
1//===-- ubsan_flags.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// UBSan runtime flags.
10//
11//===----------------------------------------------------------------------===//
12#ifndef UBSAN_FLAG
13# error "Define UBSAN_FLAG prior to including this file!"
14#endif
15
16// UBSAN_FLAG(Type, Name, DefaultValue, Description)
17// See COMMON_FLAG in sanitizer_flags.inc for more details.
18
19UBSAN_FLAG(bool, halt_on_error, false,
20 "Crash the program after printing the first error report")
21UBSAN_FLAG(bool, print_stacktrace, false,
22 "Include full stacktrace into an error report")
23UBSAN_FLAG(const char *, suppressions, "", "Suppressions file name.")
24UBSAN_FLAG(bool, report_error_type, false,
25 "Print specific error type instead of 'undefined-behavior' in summary.")
26UBSAN_FLAG(bool, silence_unsigned_overflow, false,
27 "Do not print non-fatal error reports for unsigned integer overflow. "
28 "Used to provide fuzzing signal without blowing up logs.")
lib/tsan/ubsan/ubsan_init.h created+33
...@@ -0,0 +1,33 @@
1//===-- ubsan_init.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// Initialization function for UBSan runtime.
10//
11//===----------------------------------------------------------------------===//
12#ifndef UBSAN_INIT_H
13#define UBSAN_INIT_H
14
15namespace __ubsan {
16
17// Get the full tool name for UBSan.
18const char *GetSanititizerToolName();
19
20// Initialize UBSan as a standalone tool. Typically should be called early
21// during initialization.
22void InitAsStandalone();
23
24// Initialize UBSan as a standalone tool, if it hasn't been initialized before.
25void InitAsStandaloneIfNecessary();
26
27// Initializes UBSan as a plugin tool. This function should be called once
28// from "parent tool" (e.g. ASan) initialization.
29void InitAsPlugin();
30
31} // namespace __ubsan
32
33#endif // UBSAN_INIT_H
lib/tsan/ubsan/ubsan_platform.h created+25
...@@ -0,0 +1,25 @@
1//===-- ubsan_platform.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// Defines the platforms which UBSan is supported at.
10//
11//===----------------------------------------------------------------------===//
12#ifndef UBSAN_PLATFORM_H
13#define UBSAN_PLATFORM_H
14
15// Other platforms should be easy to add, and probably work as-is.
16#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || \
17 defined(__NetBSD__) || defined(__OpenBSD__) || \
18 (defined(__sun__) && defined(__svr4__)) || \
19 defined(_WIN32) || defined(__Fuchsia__) || defined(__rtems__)
20# define CAN_SANITIZE_UB 1
21#else
22# define CAN_SANITIZE_UB 0
23#endif
24
25#endif
src/Compilation.zig+28-2
...@@ -30,6 +30,7 @@ const c_codegen = @import("codegen/c.zig");...@@ -30,6 +30,7 @@ const c_codegen = @import("codegen/c.zig");
30const c_link = @import("link/C.zig");30const c_link = @import("link/C.zig");
31const ThreadPool = @import("ThreadPool.zig");31const ThreadPool = @import("ThreadPool.zig");
32const WaitGroup = @import("WaitGroup.zig");32const WaitGroup = @import("WaitGroup.zig");
33const libtsan = @import("libtsan.zig");
3334
34/// General-purpose allocator. Used for both temporary and long-term storage.35/// General-purpose allocator. Used for both temporary and long-term storage.
35gpa: *Allocator,36gpa: *Allocator,
...@@ -94,6 +95,9 @@ libcxxabi_static_lib: ?CRTFile = null,...@@ -94,6 +95,9 @@ libcxxabi_static_lib: ?CRTFile = null,
94/// Populated when we build the libunwind static library. A Job to build this is placed in the queue95/// Populated when we build the libunwind static library. A Job to build this is placed in the queue
95/// and resolved before calling linker.flush().96/// and resolved before calling linker.flush().
96libunwind_static_lib: ?CRTFile = null,97libunwind_static_lib: ?CRTFile = null,
98/// Populated when we build the TSAN static library. A Job to build this is placed in the queue
99/// and resolved before calling linker.flush().
100tsan_static_lib: ?CRTFile = null,
97/// Populated when we build the libssp static library. A Job to build this is placed in the queue101/// Populated when we build the libssp static library. A Job to build this is placed in the queue
98/// and resolved before calling linker.flush().102/// and resolved before calling linker.flush().
99libssp_static_lib: ?CRTFile = null,103libssp_static_lib: ?CRTFile = null,
...@@ -179,6 +183,7 @@ const Job = union(enum) {...@@ -179,6 +183,7 @@ const Job = union(enum) {
179 libunwind: void,183 libunwind: void,
180 libcxx: void,184 libcxx: void,
181 libcxxabi: void,185 libcxxabi: void,
186 libtsan: void,
182 libssp: void,187 libssp: void,
183 compiler_rt_lib: void,188 compiler_rt_lib: void,
184 compiler_rt_obj: void,189 compiler_rt_obj: void,
...@@ -388,6 +393,7 @@ pub const InitOptions = struct {...@@ -388,6 +393,7 @@ pub const InitOptions = struct {
388 want_sanitize_c: ?bool = null,393 want_sanitize_c: ?bool = null,
389 want_stack_check: ?bool = null,394 want_stack_check: ?bool = null,
390 want_valgrind: ?bool = null,395 want_valgrind: ?bool = null,
396 want_tsan: ?bool = null,
391 want_compiler_rt: ?bool = null,397 want_compiler_rt: ?bool = null,
392 use_llvm: ?bool = null,398 use_llvm: ?bool = null,
393 use_lld: ?bool = null,399 use_lld: ?bool = null,
...@@ -644,13 +650,15 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -644,13 +650,15 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
644 options.libc_installation,650 options.libc_installation,
645 );651 );
646652
653 const tsan = options.want_tsan orelse false;
654
647 const must_pie = target_util.requiresPIE(options.target);655 const must_pie = target_util.requiresPIE(options.target);
648 const pie = if (options.want_pie) |explicit| pie: {656 const pie: bool = if (options.want_pie) |explicit| pie: {
649 if (!explicit and must_pie) {657 if (!explicit and must_pie) {
650 return error.TargetRequiresPIE;658 return error.TargetRequiresPIE;
651 }659 }
652 break :pie explicit;660 break :pie explicit;
653 } else must_pie;661 } else must_pie or tsan;
654662
655 const must_pic: bool = b: {663 const must_pic: bool = b: {
656 if (target_util.requiresPIC(options.target, link_libc))664 if (target_util.requiresPIC(options.target, link_libc))
...@@ -751,6 +759,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -751,6 +759,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
751 cache.hash.add(ofmt);759 cache.hash.add(ofmt);
752 cache.hash.add(pic);760 cache.hash.add(pic);
753 cache.hash.add(pie);761 cache.hash.add(pie);
762 cache.hash.add(tsan);
754 cache.hash.add(stack_check);763 cache.hash.add(stack_check);
755 cache.hash.add(link_mode);764 cache.hash.add(link_mode);
756 cache.hash.add(options.function_sections);765 cache.hash.add(options.function_sections);
...@@ -953,6 +962,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -953,6 +962,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
953 .pic = pic,962 .pic = pic,
954 .pie = pie,963 .pie = pie,
955 .valgrind = valgrind,964 .valgrind = valgrind,
965 .tsan = tsan,
956 .stack_check = stack_check,966 .stack_check = stack_check,
957 .single_threaded = single_threaded,967 .single_threaded = single_threaded,
958 .verbose_link = options.verbose_link,968 .verbose_link = options.verbose_link,
...@@ -1093,6 +1103,9 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -1093,6 +1103,9 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
1093 try comp.work_queue.writeItem(.libcxx);1103 try comp.work_queue.writeItem(.libcxx);
1094 try comp.work_queue.writeItem(.libcxxabi);1104 try comp.work_queue.writeItem(.libcxxabi);
1095 }1105 }
1106 if (build_options.have_llvm and comp.bin_file.options.tsan) {
1107 try comp.work_queue.writeItem(.libtsan);
1108 }
10961109
1097 // The `is_stage1` condition is here only because stage2 cannot yet build compiler-rt.1110 // The `is_stage1` condition is here only because stage2 cannot yet build compiler-rt.
1098 // Once it is capable this condition should be removed.1111 // Once it is capable this condition should be removed.
...@@ -1569,6 +1582,12 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor...@@ -1569,6 +1582,12 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
1569 fatal("unable to build libcxxabi: {}", .{@errorName(err)});1582 fatal("unable to build libcxxabi: {}", .{@errorName(err)});
1570 };1583 };
1571 },1584 },
1585 .libtsan => {
1586 libtsan.buildTsan(self) catch |err| {
1587 // TODO Expose this as a normal compile error rather than crashing here.
1588 fatal("unable to build TSAN library: {}", .{@errorName(err)});
1589 };
1590 },
1572 .compiler_rt_lib => {1591 .compiler_rt_lib => {
1573 self.buildOutputFromZig("compiler_rt.zig", .Lib, &self.compiler_rt_static_lib) catch |err| {1592 self.buildOutputFromZig("compiler_rt.zig", .Lib, &self.compiler_rt_static_lib) catch |err| {
1574 // TODO Expose this as a normal compile error rather than crashing here.1593 // TODO Expose this as a normal compile error rather than crashing here.
...@@ -2052,6 +2071,10 @@ pub fn addCCArgs(...@@ -2052,6 +2071,10 @@ pub fn addCCArgs(
2052 try argv.append("-ffunction-sections");2071 try argv.append("-ffunction-sections");
2053 }2072 }
20542073
2074 if (comp.bin_file.options.tsan) {
2075 try argv.append("-fsanitize=thread");
2076 }
2077
2055 try argv.ensureCapacity(argv.items.len + comp.bin_file.options.framework_dirs.len * 2);2078 try argv.ensureCapacity(argv.items.len + comp.bin_file.options.framework_dirs.len * 2);
2056 for (comp.bin_file.options.framework_dirs) |framework_dir| {2079 for (comp.bin_file.options.framework_dirs) |framework_dir| {
2057 argv.appendAssumeCapacity("-iframework");2080 argv.appendAssumeCapacity("-iframework");
...@@ -2887,6 +2910,7 @@ fn buildOutputFromZig(...@@ -2887,6 +2910,7 @@ fn buildOutputFromZig(
2887 .want_sanitize_c = false,2910 .want_sanitize_c = false,
2888 .want_stack_check = false,2911 .want_stack_check = false,
2889 .want_valgrind = false,2912 .want_valgrind = false,
2913 .want_tsan = false,
2890 .want_pic = comp.bin_file.options.pic,2914 .want_pic = comp.bin_file.options.pic,
2891 .want_pie = comp.bin_file.options.pie,2915 .want_pie = comp.bin_file.options.pie,
2892 .emit_h = null,2916 .emit_h = null,
...@@ -3115,6 +3139,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node...@@ -3115,6 +3139,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
3115 .dll_export_fns = comp.bin_file.options.dll_export_fns,3139 .dll_export_fns = comp.bin_file.options.dll_export_fns,
3116 .link_mode_dynamic = comp.bin_file.options.link_mode == .Dynamic,3140 .link_mode_dynamic = comp.bin_file.options.link_mode == .Dynamic,
3117 .valgrind_enabled = comp.bin_file.options.valgrind,3141 .valgrind_enabled = comp.bin_file.options.valgrind,
3142 .tsan_enabled = comp.bin_file.options.tsan,
3118 .function_sections = comp.bin_file.options.function_sections,3143 .function_sections = comp.bin_file.options.function_sections,
3119 .enable_stack_probing = comp.bin_file.options.stack_check,3144 .enable_stack_probing = comp.bin_file.options.stack_check,
3120 .enable_time_report = comp.time_report,3145 .enable_time_report = comp.time_report,
...@@ -3262,6 +3287,7 @@ pub fn build_crt_file(...@@ -3262,6 +3287,7 @@ pub fn build_crt_file(
3262 .want_sanitize_c = false,3287 .want_sanitize_c = false,
3263 .want_stack_check = false,3288 .want_stack_check = false,
3264 .want_valgrind = false,3289 .want_valgrind = false,
3290 .want_tsan = false,
3265 .want_pic = comp.bin_file.options.pic,3291 .want_pic = comp.bin_file.options.pic,
3266 .want_pie = comp.bin_file.options.pie,3292 .want_pie = comp.bin_file.options.pie,
3267 .emit_h = null,3293 .emit_h = null,
src/glibc.zig+1
...@@ -943,6 +943,7 @@ fn buildSharedLib(...@@ -943,6 +943,7 @@ fn buildSharedLib(
943 .want_sanitize_c = false,943 .want_sanitize_c = false,
944 .want_stack_check = false,944 .want_stack_check = false,
945 .want_valgrind = false,945 .want_valgrind = false,
946 .want_tsan = false,
946 .emit_h = null,947 .emit_h = null,
947 .strip = comp.bin_file.options.strip,948 .strip = comp.bin_file.options.strip,
948 .is_native_os = false,949 .is_native_os = false,
src/libcxx.zig+2-1
...@@ -139,7 +139,6 @@ pub fn buildLibCXX(comp: *Compilation) !void {...@@ -139,7 +139,6 @@ pub fn buildLibCXX(comp: *Compilation) !void {
139 try cflags.append(cxxabi_include_path);139 try cflags.append(cxxabi_include_path);
140140
141 try cflags.append("-O3");141 try cflags.append("-O3");
142 try cflags.append("-DNDEBUG");
143 if (target_util.supports_fpic(target)) {142 if (target_util.supports_fpic(target)) {
144 try cflags.append("-fPIC");143 try cflags.append("-fPIC");
145 }144 }
...@@ -170,6 +169,7 @@ pub fn buildLibCXX(comp: *Compilation) !void {...@@ -170,6 +169,7 @@ pub fn buildLibCXX(comp: *Compilation) !void {
170 .want_sanitize_c = false,169 .want_sanitize_c = false,
171 .want_stack_check = false,170 .want_stack_check = false,
172 .want_valgrind = false,171 .want_valgrind = false,
172 .want_tsan = comp.bin_file.options.tsan,
173 .want_pic = comp.bin_file.options.pic,173 .want_pic = comp.bin_file.options.pic,
174 .want_pie = comp.bin_file.options.pie,174 .want_pie = comp.bin_file.options.pie,
175 .emit_h = null,175 .emit_h = null,
...@@ -289,6 +289,7 @@ pub fn buildLibCXXABI(comp: *Compilation) !void {...@@ -289,6 +289,7 @@ pub fn buildLibCXXABI(comp: *Compilation) !void {
289 .want_sanitize_c = false,289 .want_sanitize_c = false,
290 .want_stack_check = false,290 .want_stack_check = false,
291 .want_valgrind = false,291 .want_valgrind = false,
292 .want_tsan = comp.bin_file.options.tsan,
292 .want_pic = comp.bin_file.options.pic,293 .want_pic = comp.bin_file.options.pic,
293 .want_pie = comp.bin_file.options.pie,294 .want_pie = comp.bin_file.options.pie,
294 .emit_h = null,295 .emit_h = null,
src/libtsan.zig created+219
...@@ -0,0 +1,219 @@
1const std = @import("std");
2const assert = std.debug.assert;
3
4const Compilation = @import("Compilation.zig");
5const build_options = @import("build_options");
6const trace = @import("tracy.zig").trace;
7
8pub fn buildTsan(comp: *Compilation) !void {
9 if (!build_options.have_llvm) {
10 return error.ZigCompilerNotBuiltWithLLVMExtensions;
11 }
12
13 const tracy = trace(@src());
14 defer tracy.end();
15
16 var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);
17 defer arena_allocator.deinit();
18 const arena = &arena_allocator.allocator;
19
20 const root_name = "tsan";
21 const output_mode = .Lib;
22 const link_mode = .Static;
23 const target = comp.getTarget();
24 const basename = try std.zig.binNameAlloc(arena, .{
25 .root_name = root_name,
26 .target = target,
27 .output_mode = output_mode,
28 .link_mode = link_mode,
29 });
30
31 const emit_bin = Compilation.EmitLoc{
32 .directory = null, // Put it in the cache directory.
33 .basename = basename,
34 };
35
36 var c_source_files = std.ArrayList(Compilation.CSourceFile).init(arena);
37 try c_source_files.ensureCapacity(tsan_sources.len + sanitizer_common_sources.len);
38
39 const tsan_include_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{"tsan"});
40 for (tsan_sources) |tsan_src| {
41 var cflags = std.ArrayList([]const u8).init(arena);
42
43 try cflags.append("-I");
44 try cflags.append(tsan_include_path);
45
46 try cflags.append("-O3");
47 try cflags.append("-DNDEBUG");
48 try cflags.append("-nostdinc++");
49 try cflags.append("-fvisibility-inlines-hidden");
50 try cflags.append("-std=c++14");
51
52 c_source_files.appendAssumeCapacity(.{
53 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "tsan", tsan_src }),
54 .extra_flags = cflags.items,
55 });
56 }
57
58 const sanitizer_common_include_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
59 "tsan", "sanitizer_common",
60 });
61 for (sanitizer_common_sources) |common_src| {
62 var cflags = std.ArrayList([]const u8).init(arena);
63
64 try cflags.append("-I");
65 try cflags.append(sanitizer_common_include_path);
66
67 try cflags.append("-O3");
68 try cflags.append("-DNDEBUG");
69 try cflags.append("-nostdinc++");
70 try cflags.append("-fvisibility-inlines-hidden");
71 try cflags.append("-std=c++14");
72
73 c_source_files.appendAssumeCapacity(.{
74 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
75 "tsan", "sanitizer_common", common_src,
76 }),
77 .extra_flags = cflags.items,
78 });
79 }
80
81 const sub_compilation = try Compilation.create(comp.gpa, .{
82 .local_cache_directory = comp.global_cache_directory,
83 .global_cache_directory = comp.global_cache_directory,
84 .zig_lib_directory = comp.zig_lib_directory,
85 .target = target,
86 .root_name = root_name,
87 .root_pkg = null,
88 .output_mode = output_mode,
89 .thread_pool = comp.thread_pool,
90 .libc_installation = comp.bin_file.options.libc_installation,
91 .emit_bin = emit_bin,
92 .optimize_mode = comp.bin_file.options.optimize_mode,
93 .link_mode = link_mode,
94 .want_sanitize_c = false,
95 .want_stack_check = false,
96 .want_valgrind = false,
97 .want_tsan = false,
98 .want_pic = true,
99 .want_pie = true,
100 .emit_h = null,
101 .strip = comp.bin_file.options.strip,
102 .is_native_os = comp.bin_file.options.is_native_os,
103 .is_native_abi = comp.bin_file.options.is_native_abi,
104 .self_exe_path = comp.self_exe_path,
105 .c_source_files = c_source_files.items,
106 .verbose_cc = comp.verbose_cc,
107 .verbose_link = comp.bin_file.options.verbose_link,
108 .verbose_tokenize = comp.verbose_tokenize,
109 .verbose_ast = comp.verbose_ast,
110 .verbose_ir = comp.verbose_ir,
111 .verbose_llvm_ir = comp.verbose_llvm_ir,
112 .verbose_cimport = comp.verbose_cimport,
113 .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
114 .clang_passthrough_mode = comp.clang_passthrough_mode,
115 .link_libc = true,
116 });
117 defer sub_compilation.destroy();
118
119 try sub_compilation.updateSubCompilation();
120
121 assert(comp.tsan_static_lib == null);
122 comp.tsan_static_lib = Compilation.CRTFile{
123 .full_object_path = try sub_compilation.bin_file.options.emit.?.directory.join(
124 comp.gpa,
125 &[_][]const u8{basename},
126 ),
127 .lock = sub_compilation.bin_file.toOwnedLock(),
128 };
129}
130
131const tsan_sources = [_][]const u8{
132 "tsan_clock.cpp",
133 "tsan_debugging.cpp",
134 "tsan_external.cpp",
135 "tsan_fd.cpp",
136 "tsan_flags.cpp",
137 "tsan_ignoreset.cpp",
138 "tsan_interceptors_posix.cpp",
139 "tsan_interface.cpp",
140 "tsan_interface_ann.cpp",
141 "tsan_interface_atomic.cpp",
142 "tsan_interface_java.cpp",
143 "tsan_malloc_mac.cpp",
144 "tsan_md5.cpp",
145 "tsan_mman.cpp",
146 "tsan_mutex.cpp",
147 "tsan_mutexset.cpp",
148 "tsan_preinit.cpp",
149 "tsan_report.cpp",
150 "tsan_rtl.cpp",
151 "tsan_rtl_mutex.cpp",
152 "tsan_rtl_proc.cpp",
153 "tsan_rtl_report.cpp",
154 "tsan_rtl_thread.cpp",
155 "tsan_stack_trace.cpp",
156 "tsan_stat.cpp",
157 "tsan_suppressions.cpp",
158 "tsan_symbolize.cpp",
159 "tsan_sync.cpp",
160};
161
162const sanitizer_common_sources = [_][]const u8{
163 "sanitizer_allocator.cpp",
164 "sanitizer_common.cpp",
165 "sanitizer_deadlock_detector1.cpp",
166 "sanitizer_deadlock_detector2.cpp",
167 "sanitizer_errno.cpp",
168 "sanitizer_file.cpp",
169 "sanitizer_flags.cpp",
170 "sanitizer_flag_parser.cpp",
171 "sanitizer_fuchsia.cpp",
172 "sanitizer_libc.cpp",
173 "sanitizer_libignore.cpp",
174 "sanitizer_linux.cpp",
175 "sanitizer_linux_s390.cpp",
176 "sanitizer_mac.cpp",
177 "sanitizer_netbsd.cpp",
178 "sanitizer_openbsd.cpp",
179 "sanitizer_persistent_allocator.cpp",
180 "sanitizer_platform_limits_freebsd.cpp",
181 "sanitizer_platform_limits_linux.cpp",
182 "sanitizer_platform_limits_netbsd.cpp",
183 "sanitizer_platform_limits_openbsd.cpp",
184 "sanitizer_platform_limits_posix.cpp",
185 "sanitizer_platform_limits_solaris.cpp",
186 "sanitizer_posix.cpp",
187 "sanitizer_printf.cpp",
188 "sanitizer_procmaps_common.cpp",
189 "sanitizer_procmaps_bsd.cpp",
190 "sanitizer_procmaps_fuchsia.cpp",
191 "sanitizer_procmaps_linux.cpp",
192 "sanitizer_procmaps_mac.cpp",
193 "sanitizer_procmaps_solaris.cpp",
194 "sanitizer_rtems.cpp",
195 "sanitizer_solaris.cpp",
196 "sanitizer_stoptheworld_fuchsia.cpp",
197 "sanitizer_stoptheworld_mac.cpp",
198 "sanitizer_suppressions.cpp",
199 "sanitizer_termination.cpp",
200 "sanitizer_tls_get_addr.cpp",
201 "sanitizer_thread_registry.cpp",
202 "sanitizer_type_traits.cpp",
203 "sanitizer_win.cpp",
204};
205
206// TODO This is next up
207//const sanitizer_nolibc_sources = [_][]const u8{
208// "sanitizer_common_nolibc.cpp",
209//};
210//
211//const sanitizer_libcdep_sources = [_][]const u8{
212// "sanitizer_common_libcdep.cpp",
213// "sanitizer_allocator_checks.cpp",
214// "sanitizer_linux_libcdep.cpp",
215// "sanitizer_mac_libcdep.cpp",
216// "sanitizer_posix_libcdep.cpp",
217// "sanitizer_stoptheworld_linux_libcdep.cpp",
218// "sanitizer_stoptheworld_netbsd_libcdep.cpp",
219//};
src/libunwind.zig+1
...@@ -103,6 +103,7 @@ pub fn buildStaticLib(comp: *Compilation) !void {...@@ -103,6 +103,7 @@ pub fn buildStaticLib(comp: *Compilation) !void {
103 .want_sanitize_c = false,103 .want_sanitize_c = false,
104 .want_stack_check = false,104 .want_stack_check = false,
105 .want_valgrind = false,105 .want_valgrind = false,
106 .want_tsan = false,
106 .want_pic = comp.bin_file.options.pic,107 .want_pic = comp.bin_file.options.pic,
107 .want_pie = comp.bin_file.options.pie,108 .want_pie = comp.bin_file.options.pie,
108 .emit_h = null,109 .emit_h = null,
src/link.zig+1
...@@ -75,6 +75,7 @@ pub const Options = struct {...@@ -75,6 +75,7 @@ pub const Options = struct {
75 pic: bool,75 pic: bool,
76 pie: bool,76 pie: bool,
77 valgrind: bool,77 valgrind: bool,
78 tsan: bool,
78 stack_check: bool,79 stack_check: bool,
79 single_threaded: bool,80 single_threaded: bool,
80 verbose_link: bool,81 verbose_link: bool,
src/link/Elf.zig+6
...@@ -1327,6 +1327,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1327,6 +1327,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1327 man.hash.addStringSet(self.base.options.system_libs);1327 man.hash.addStringSet(self.base.options.system_libs);
1328 man.hash.add(allow_shlib_undefined);1328 man.hash.add(allow_shlib_undefined);
1329 man.hash.add(self.base.options.bind_global_refs_locally);1329 man.hash.add(self.base.options.bind_global_refs_locally);
1330 man.hash.add(self.base.options.tsan);
13301331
1331 // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.1332 // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.
1332 _ = try man.hit();1333 _ = try man.hit();
...@@ -1545,6 +1546,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1545,6 +1546,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1545 try argv.append(p);1546 try argv.append(p);
1546 }1547 }
15471548
1549 // TSAN
1550 if (self.base.options.tsan) {
1551 try argv.append(comp.tsan_static_lib.?.full_object_path);
1552 }
1553
1548 // libc1554 // libc
1549 if (is_exe_or_dyn_lib and !self.base.options.is_compiler_rt_or_libc and !self.base.options.link_libc) {1555 if (is_exe_or_dyn_lib and !self.base.options.is_compiler_rt_or_libc and !self.base.options.link_libc) {
1550 try argv.append(comp.libc_static_lib.?.full_object_path);1556 try argv.append(comp.libc_static_lib.?.full_object_path);
src/main.zig+10
...@@ -285,6 +285,8 @@ const usage_build_generic =...@@ -285,6 +285,8 @@ const usage_build_generic =
285 \\ -fno-sanitize-c Disable C undefined behavior detection in safe builds285 \\ -fno-sanitize-c Disable C undefined behavior detection in safe builds
286 \\ -fvalgrind Include valgrind client requests in release builds286 \\ -fvalgrind Include valgrind client requests in release builds
287 \\ -fno-valgrind Omit valgrind client requests in debug builds287 \\ -fno-valgrind Omit valgrind client requests in debug builds
288 \\ -fsanitize-thread Enable Thread Sanitizer
289 \\ -fno-sanitize-thread Disable Thread Sanitizer
288 \\ -fdll-export-fns Mark exported functions as DLL exports (Windows)290 \\ -fdll-export-fns Mark exported functions as DLL exports (Windows)
289 \\ -fno-dll-export-fns Force-disable marking exported functions as DLL exports291 \\ -fno-dll-export-fns Force-disable marking exported functions as DLL exports
290 \\ -fLLVM Force using LLVM as the codegen backend292 \\ -fLLVM Force using LLVM as the codegen backend
...@@ -503,6 +505,7 @@ fn buildOutputType(...@@ -503,6 +505,7 @@ fn buildOutputType(
503 var want_sanitize_c: ?bool = null;505 var want_sanitize_c: ?bool = null;
504 var want_stack_check: ?bool = null;506 var want_stack_check: ?bool = null;
505 var want_valgrind: ?bool = null;507 var want_valgrind: ?bool = null;
508 var want_tsan: ?bool = null;
506 var want_compiler_rt: ?bool = null;509 var want_compiler_rt: ?bool = null;
507 var rdynamic: bool = false;510 var rdynamic: bool = false;
508 var linker_script: ?[]const u8 = null;511 var linker_script: ?[]const u8 = null;
...@@ -847,6 +850,10 @@ fn buildOutputType(...@@ -847,6 +850,10 @@ fn buildOutputType(
847 want_valgrind = true;850 want_valgrind = true;
848 } else if (mem.eql(u8, arg, "-fno-valgrind")) {851 } else if (mem.eql(u8, arg, "-fno-valgrind")) {
849 want_valgrind = false;852 want_valgrind = false;
853 } else if (mem.eql(u8, arg, "-fsanitize-thread")) {
854 want_tsan = true;
855 } else if (mem.eql(u8, arg, "-fno-sanitize-thread")) {
856 want_tsan = false;
850 } else if (mem.eql(u8, arg, "-fLLVM")) {857 } else if (mem.eql(u8, arg, "-fLLVM")) {
851 use_llvm = true;858 use_llvm = true;
852 } else if (mem.eql(u8, arg, "-fno-LLVM")) {859 } else if (mem.eql(u8, arg, "-fno-LLVM")) {
...@@ -1106,6 +1113,8 @@ fn buildOutputType(...@@ -1106,6 +1113,8 @@ fn buildOutputType(
1106 .sanitize => {1113 .sanitize => {
1107 if (mem.eql(u8, it.only_arg, "undefined")) {1114 if (mem.eql(u8, it.only_arg, "undefined")) {
1108 want_sanitize_c = true;1115 want_sanitize_c = true;
1116 } else if (mem.eql(u8, it.only_arg, "thread")) {
1117 want_tsan = true;
1109 } else {1118 } else {
1110 try clang_argv.appendSlice(it.other_args);1119 try clang_argv.appendSlice(it.other_args);
1111 }1120 }
...@@ -1712,6 +1721,7 @@ fn buildOutputType(...@@ -1712,6 +1721,7 @@ fn buildOutputType(
1712 .want_sanitize_c = want_sanitize_c,1721 .want_sanitize_c = want_sanitize_c,
1713 .want_stack_check = want_stack_check,1722 .want_stack_check = want_stack_check,
1714 .want_valgrind = want_valgrind,1723 .want_valgrind = want_valgrind,
1724 .want_tsan = want_tsan,
1715 .want_compiler_rt = want_compiler_rt,1725 .want_compiler_rt = want_compiler_rt,
1716 .use_llvm = use_llvm,1726 .use_llvm = use_llvm,
1717 .use_lld = use_lld,1727 .use_lld = use_lld,
src/musl.zig+1
...@@ -207,6 +207,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void {...@@ -207,6 +207,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void {
207 .want_sanitize_c = false,207 .want_sanitize_c = false,
208 .want_stack_check = false,208 .want_stack_check = false,
209 .want_valgrind = false,209 .want_valgrind = false,
210 .want_tsan = false,
210 .emit_h = null,211 .emit_h = null,
211 .strip = comp.bin_file.options.strip,212 .strip = comp.bin_file.options.strip,
212 .is_native_os = false,213 .is_native_os = false,
src/stage1.zig+1
...@@ -116,6 +116,7 @@ pub const Module = extern struct {...@@ -116,6 +116,7 @@ pub const Module = extern struct {
116 dll_export_fns: bool,116 dll_export_fns: bool,
117 link_mode_dynamic: bool,117 link_mode_dynamic: bool,
118 valgrind_enabled: bool,118 valgrind_enabled: bool,
119 tsan_enabled: bool,
119 function_sections: bool,120 function_sections: bool,
120 enable_stack_probing: bool,121 enable_stack_probing: bool,
121 enable_time_report: bool,122 enable_time_report: bool,
src/stage1/all_types.hpp+1
...@@ -2199,6 +2199,7 @@ struct CodeGen {...@@ -2199,6 +2199,7 @@ struct CodeGen {
2199 bool function_sections;2199 bool function_sections;
2200 bool test_is_evented;2200 bool test_is_evented;
2201 bool valgrind_enabled;2201 bool valgrind_enabled;
2202 bool tsan_enabled;
22022203
2203 Buf *root_out_name;2204 Buf *root_out_name;
2204 Buf *test_filter;2205 Buf *test_filter;
src/stage1/codegen.cpp+4
...@@ -472,6 +472,10 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) {...@@ -472,6 +472,10 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) {
472 ZigLLVMFunctionSetCallingConv(llvm_fn, get_llvm_cc(g, cc));472 ZigLLVMFunctionSetCallingConv(llvm_fn, get_llvm_cc(g, cc));
473 }473 }
474474
475 if (g->tsan_enabled) {
476 addLLVMFnAttr(llvm_fn, "sanitize_thread");
477 }
478
475 bool want_cold = fn->is_cold;479 bool want_cold = fn->is_cold;
476 if (want_cold) {480 if (want_cold) {
477 ZigLLVMAddFunctionAttrCold(llvm_fn);481 ZigLLVMAddFunctionAttrCold(llvm_fn);
src/stage1/stage1.cpp+1
...@@ -93,6 +93,7 @@ void zig_stage1_build_object(struct ZigStage1 *stage1) {...@@ -93,6 +93,7 @@ void zig_stage1_build_object(struct ZigStage1 *stage1) {
93 g->have_stack_probing = stage1->enable_stack_probing;93 g->have_stack_probing = stage1->enable_stack_probing;
94 g->is_single_threaded = stage1->is_single_threaded;94 g->is_single_threaded = stage1->is_single_threaded;
95 g->valgrind_enabled = stage1->valgrind_enabled;95 g->valgrind_enabled = stage1->valgrind_enabled;
96 g->tsan_enabled = stage1->tsan_enabled;
96 g->link_libc = stage1->link_libc;97 g->link_libc = stage1->link_libc;
97 g->link_libcpp = stage1->link_libcpp;98 g->link_libcpp = stage1->link_libcpp;
98 g->function_sections = stage1->function_sections;99 g->function_sections = stage1->function_sections;
src/stage1/stage1.h+1
...@@ -185,6 +185,7 @@ struct ZigStage1 {...@@ -185,6 +185,7 @@ struct ZigStage1 {
185 bool dll_export_fns;185 bool dll_export_fns;
186 bool link_mode_dynamic;186 bool link_mode_dynamic;
187 bool valgrind_enabled;187 bool valgrind_enabled;
188 bool tsan_enabled;
188 bool function_sections;189 bool function_sections;
189 bool enable_stack_probing;190 bool enable_stack_probing;
190 bool enable_time_report;191 bool enable_time_report;