authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2024-09-24 13:47:29+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-09-24 23:58:21-07:00
loga40cdad18c06fd377622c47aa34564df7ea959b5
treedbcfabc2191cdbf2acc6c356c5ea25237b29d8f1
parent7f6b7c56089eaa5b147e71b3d98328498c9025c8

tsan: Update to LLVM 19.1.0.


130 files changed, 4952 insertions(+), 2618 deletions(-)

lib/tsan/builtins/assembly.h created+293
......@@ -0,0 +1,293 @@
1//===-- assembly.h - compiler-rt assembler support macros -----------------===//
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 macros for use in compiler-rt assembler source.
10// This file is not part of the interface of this library.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef COMPILERRT_ASSEMBLY_H
15#define COMPILERRT_ASSEMBLY_H
16
17#if defined(__linux__) && defined(__CET__)
18#if __has_include(<cet.h>)
19#include <cet.h>
20#endif
21#endif
22
23#if defined(__APPLE__) && defined(__aarch64__)
24#define SEPARATOR %%
25#else
26#define SEPARATOR ;
27#endif
28
29#if defined(__APPLE__)
30#define HIDDEN(name) .private_extern name
31#define LOCAL_LABEL(name) L_##name
32// tell linker it can break up file at label boundaries
33#define FILE_LEVEL_DIRECTIVE .subsections_via_symbols
34#define SYMBOL_IS_FUNC(name)
35#define CONST_SECTION .const
36
37#define NO_EXEC_STACK_DIRECTIVE
38
39#elif defined(__ELF__)
40
41#define HIDDEN(name) .hidden name
42#define LOCAL_LABEL(name) .L_##name
43#define FILE_LEVEL_DIRECTIVE
44#if defined(__arm__) || defined(__aarch64__)
45#define SYMBOL_IS_FUNC(name) .type name,%function
46#else
47#define SYMBOL_IS_FUNC(name) .type name,@function
48#endif
49#define CONST_SECTION .section .rodata
50
51#if defined(__GNU__) || defined(__FreeBSD__) || defined(__Fuchsia__) || \
52 defined(__linux__)
53#define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits
54#else
55#define NO_EXEC_STACK_DIRECTIVE
56#endif
57
58#else // !__APPLE__ && !__ELF__
59
60#define HIDDEN(name)
61#define LOCAL_LABEL(name) .L ## name
62#define FILE_LEVEL_DIRECTIVE
63#define SYMBOL_IS_FUNC(name) \
64 .def name SEPARATOR \
65 .scl 2 SEPARATOR \
66 .type 32 SEPARATOR \
67 .endef
68#define CONST_SECTION .section .rdata,"rd"
69
70#define NO_EXEC_STACK_DIRECTIVE
71
72#endif
73
74#if defined(__arm__) || defined(__aarch64__)
75#define FUNC_ALIGN \
76 .text SEPARATOR \
77 .balign 16 SEPARATOR
78#else
79#define FUNC_ALIGN
80#endif
81
82// BTI and PAC gnu property note
83#define NT_GNU_PROPERTY_TYPE_0 5
84#define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000
85#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI 1
86#define GNU_PROPERTY_AARCH64_FEATURE_1_PAC 2
87
88#if defined(__ARM_FEATURE_BTI_DEFAULT)
89#define BTI_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_BTI
90#else
91#define BTI_FLAG 0
92#endif
93
94#if __ARM_FEATURE_PAC_DEFAULT & 3
95#define PAC_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_PAC
96#else
97#define PAC_FLAG 0
98#endif
99
100#define GNU_PROPERTY(type, value) \
101 .pushsection .note.gnu.property, "a" SEPARATOR \
102 .p2align 3 SEPARATOR \
103 .word 4 SEPARATOR \
104 .word 16 SEPARATOR \
105 .word NT_GNU_PROPERTY_TYPE_0 SEPARATOR \
106 .asciz "GNU" SEPARATOR \
107 .word type SEPARATOR \
108 .word 4 SEPARATOR \
109 .word value SEPARATOR \
110 .word 0 SEPARATOR \
111 .popsection
112
113#if BTI_FLAG != 0
114#define BTI_C hint #34
115#define BTI_J hint #36
116#else
117#define BTI_C
118#define BTI_J
119#endif
120
121#if (BTI_FLAG | PAC_FLAG) != 0
122#define GNU_PROPERTY_BTI_PAC \
123 GNU_PROPERTY(GNU_PROPERTY_AARCH64_FEATURE_1_AND, BTI_FLAG | PAC_FLAG)
124#else
125#define GNU_PROPERTY_BTI_PAC
126#endif
127
128#if defined(__clang__) || defined(__GCC_HAVE_DWARF2_CFI_ASM)
129#define CFI_START .cfi_startproc
130#define CFI_END .cfi_endproc
131#else
132#define CFI_START
133#define CFI_END
134#endif
135
136#if defined(__arm__)
137
138// Determine actual [ARM][THUMB[1][2]] ISA using compiler predefined macros:
139// - for '-mthumb -march=armv6' compiler defines '__thumb__'
140// - for '-mthumb -march=armv7' compiler defines '__thumb__' and '__thumb2__'
141#if defined(__thumb2__) || defined(__thumb__)
142#define DEFINE_CODE_STATE .thumb SEPARATOR
143#define DECLARE_FUNC_ENCODING .thumb_func SEPARATOR
144#if defined(__thumb2__)
145#define USE_THUMB_2
146#define IT(cond) it cond
147#define ITT(cond) itt cond
148#define ITE(cond) ite cond
149#else
150#define USE_THUMB_1
151#define IT(cond)
152#define ITT(cond)
153#define ITE(cond)
154#endif // defined(__thumb__2)
155#else // !defined(__thumb2__) && !defined(__thumb__)
156#define DEFINE_CODE_STATE .arm SEPARATOR
157#define DECLARE_FUNC_ENCODING
158#define IT(cond)
159#define ITT(cond)
160#define ITE(cond)
161#endif
162
163#if defined(USE_THUMB_1) && defined(USE_THUMB_2)
164#error "USE_THUMB_1 and USE_THUMB_2 can't be defined together."
165#endif
166
167#if defined(__ARM_ARCH_4T__) || __ARM_ARCH >= 5
168#define ARM_HAS_BX
169#endif
170#if !defined(__ARM_FEATURE_CLZ) && !defined(USE_THUMB_1) && \
171 (__ARM_ARCH >= 6 || (__ARM_ARCH == 5 && !defined(__ARM_ARCH_5__)))
172#define __ARM_FEATURE_CLZ
173#endif
174
175#ifdef ARM_HAS_BX
176#define JMP(r) bx r
177#define JMPc(r, c) bx##c r
178#else
179#define JMP(r) mov pc, r
180#define JMPc(r, c) mov##c pc, r
181#endif
182
183// pop {pc} can't switch Thumb mode on ARMv4T
184#if __ARM_ARCH >= 5
185#define POP_PC() pop {pc}
186#else
187#define POP_PC() \
188 pop {ip}; \
189 JMP(ip)
190#endif
191
192#if defined(USE_THUMB_2)
193#define WIDE(op) op.w
194#else
195#define WIDE(op) op
196#endif
197#else // !defined(__arm)
198#define DECLARE_FUNC_ENCODING
199#define DEFINE_CODE_STATE
200#endif
201
202#define GLUE2_(a, b) a##b
203#define GLUE(a, b) GLUE2_(a, b)
204#define GLUE2(a, b) GLUE2_(a, b)
205#define GLUE3_(a, b, c) a##b##c
206#define GLUE3(a, b, c) GLUE3_(a, b, c)
207#define GLUE4_(a, b, c, d) a##b##c##d
208#define GLUE4(a, b, c, d) GLUE4_(a, b, c, d)
209
210#define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name)
211
212#ifdef VISIBILITY_HIDDEN
213#define DECLARE_SYMBOL_VISIBILITY(name) \
214 HIDDEN(SYMBOL_NAME(name)) SEPARATOR
215#define DECLARE_SYMBOL_VISIBILITY_UNMANGLED(name) \
216 HIDDEN(name) SEPARATOR
217#else
218#define DECLARE_SYMBOL_VISIBILITY(name)
219#define DECLARE_SYMBOL_VISIBILITY_UNMANGLED(name)
220#endif
221
222#define DEFINE_COMPILERRT_FUNCTION(name) \
223 DEFINE_CODE_STATE \
224 FILE_LEVEL_DIRECTIVE SEPARATOR \
225 .globl SYMBOL_NAME(name) SEPARATOR \
226 SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
227 DECLARE_SYMBOL_VISIBILITY(name) \
228 DECLARE_FUNC_ENCODING \
229 SYMBOL_NAME(name):
230
231#define DEFINE_COMPILERRT_THUMB_FUNCTION(name) \
232 DEFINE_CODE_STATE \
233 FILE_LEVEL_DIRECTIVE SEPARATOR \
234 .globl SYMBOL_NAME(name) SEPARATOR \
235 SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
236 DECLARE_SYMBOL_VISIBILITY(name) SEPARATOR \
237 .thumb_func SEPARATOR \
238 SYMBOL_NAME(name):
239
240#define DEFINE_COMPILERRT_PRIVATE_FUNCTION(name) \
241 DEFINE_CODE_STATE \
242 FILE_LEVEL_DIRECTIVE SEPARATOR \
243 .globl SYMBOL_NAME(name) SEPARATOR \
244 SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
245 HIDDEN(SYMBOL_NAME(name)) SEPARATOR \
246 DECLARE_FUNC_ENCODING \
247 SYMBOL_NAME(name):
248
249#define DEFINE_COMPILERRT_PRIVATE_FUNCTION_UNMANGLED(name) \
250 DEFINE_CODE_STATE \
251 .globl name SEPARATOR \
252 SYMBOL_IS_FUNC(name) SEPARATOR \
253 HIDDEN(name) SEPARATOR \
254 DECLARE_FUNC_ENCODING \
255 name:
256
257#define DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(name) \
258 DEFINE_CODE_STATE \
259 FUNC_ALIGN \
260 .globl name SEPARATOR \
261 SYMBOL_IS_FUNC(name) SEPARATOR \
262 DECLARE_SYMBOL_VISIBILITY_UNMANGLED(name) SEPARATOR \
263 DECLARE_FUNC_ENCODING \
264 name: \
265 SEPARATOR CFI_START \
266 SEPARATOR BTI_C
267
268#define DEFINE_COMPILERRT_FUNCTION_ALIAS(name, target) \
269 .globl SYMBOL_NAME(name) SEPARATOR \
270 SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
271 DECLARE_SYMBOL_VISIBILITY(name) SEPARATOR \
272 .set SYMBOL_NAME(name), SYMBOL_NAME(target) SEPARATOR
273
274#if defined(__ARM_EABI__)
275#define DEFINE_AEABI_FUNCTION_ALIAS(aeabi_name, name) \
276 DEFINE_COMPILERRT_FUNCTION_ALIAS(aeabi_name, name)
277#else
278#define DEFINE_AEABI_FUNCTION_ALIAS(aeabi_name, name)
279#endif
280
281#ifdef __ELF__
282#define END_COMPILERRT_FUNCTION(name) \
283 .size SYMBOL_NAME(name), . - SYMBOL_NAME(name)
284#define END_COMPILERRT_OUTLINE_FUNCTION(name) \
285 CFI_END SEPARATOR \
286 .size SYMBOL_NAME(name), . - SYMBOL_NAME(name)
287#else
288#define END_COMPILERRT_FUNCTION(name)
289#define END_COMPILERRT_OUTLINE_FUNCTION(name) \
290 CFI_END
291#endif
292
293#endif // COMPILERRT_ASSEMBLY_H
lib/tsan/interception/interception.h+24-5
......@@ -185,6 +185,11 @@ const interpose_substitution substitution_##func_name[] \
185185# else
186186# define __ASM_WEAK_WRAPPER(func) ".weak " #func "\n"
187187# endif // SANITIZER_FREEBSD || SANITIZER_NETBSD
188# if defined(__arm__) || defined(__aarch64__)
189# define ASM_TYPE_FUNCTION_STR "%function"
190# else
191# define ASM_TYPE_FUNCTION_STR "@function"
192# endif
188193// Keep trampoline implementation in sync with sanitizer_common/sanitizer_asm.h
189194# define DECLARE_WRAPPER(ret_type, func, ...) \
190195 extern "C" ret_type func(__VA_ARGS__); \
......@@ -196,12 +201,14 @@ const interpose_substitution substitution_##func_name[] \
196201 __ASM_WEAK_WRAPPER(func) \
197202 ".set " #func ", " SANITIZER_STRINGIFY(TRAMPOLINE(func)) "\n" \
198203 ".globl " SANITIZER_STRINGIFY(TRAMPOLINE(func)) "\n" \
199 ".type " SANITIZER_STRINGIFY(TRAMPOLINE(func)) ", %function\n" \
204 ".type " SANITIZER_STRINGIFY(TRAMPOLINE(func)) ", " \
205 ASM_TYPE_FUNCTION_STR "\n" \
200206 SANITIZER_STRINGIFY(TRAMPOLINE(func)) ":\n" \
201 SANITIZER_STRINGIFY(CFI_STARTPROC) "\n" \
202 SANITIZER_STRINGIFY(ASM_TAIL_CALL) " __interceptor_" \
203 SANITIZER_STRINGIFY(ASM_PREEMPTIBLE_SYM(func)) "\n" \
204 SANITIZER_STRINGIFY(CFI_ENDPROC) "\n" \
207 C_ASM_STARTPROC "\n" \
208 C_ASM_TAIL_CALL(SANITIZER_STRINGIFY(TRAMPOLINE(func)), \
209 "__interceptor_" \
210 SANITIZER_STRINGIFY(ASM_PREEMPTIBLE_SYM(func))) "\n" \
211 C_ASM_ENDPROC "\n" \
205212 ".size " SANITIZER_STRINGIFY(TRAMPOLINE(func)) ", " \
206213 ".-" SANITIZER_STRINGIFY(TRAMPOLINE(func)) "\n" \
207214 );
......@@ -341,6 +348,18 @@ typedef unsigned long long uptr;
341348#else
342349typedef unsigned long uptr;
343350#endif // _WIN64
351
352#if defined(__ELF__) && !SANITIZER_FUCHSIA
353// The use of interceptors makes many sanitizers unusable for static linking.
354// Define a function, if called, will cause a linker error (undefined _DYNAMIC).
355// However, -static-pie (which is not common) cannot be detected at link time.
356extern uptr kDynamic[] asm("_DYNAMIC");
357inline void DoesNotSupportStaticLinking() {
358 [[maybe_unused]] volatile auto x = &kDynamic;
359}
360#else
361inline void DoesNotSupportStaticLinking() {}
362#endif
344363} // namespace __interception
345364
346365#define INCLUDED_FROM_INTERCEPTION_LIB
lib/tsan/interception/interception_linux.h+9-7
......@@ -28,12 +28,14 @@ bool InterceptFunction(const char *name, const char *ver, uptr *ptr_to_real,
2828 uptr func, uptr trampoline);
2929} // namespace __interception
3030
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)&TRAMPOLINE(func))
31// Cast func to type of REAL(func) before casting to uptr in case it is an
32// overloaded function, which is the case for some glibc functions when
33// _FORTIFY_SOURCE is used. This disambiguates which overload to use.
34#define INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func) \
35 ::__interception::InterceptFunction( \
36 #func, (::__interception::uptr *)&REAL(func), \
37 (::__interception::uptr)(decltype(REAL(func)))&(func), \
38 (::__interception::uptr) &TRAMPOLINE(func))
3739
3840// dlvsym is a GNU extension supported by some other platforms.
3941#if SANITIZER_GLIBC || SANITIZER_FREEBSD || SANITIZER_NETBSD
......@@ -41,7 +43,7 @@ bool InterceptFunction(const char *name, const char *ver, uptr *ptr_to_real,
4143 ::__interception::InterceptFunction( \
4244 #func, symver, \
4345 (::__interception::uptr *)&REAL(func), \
44 (::__interception::uptr)&(func), \
46 (::__interception::uptr)(decltype(REAL(func)))&(func), \
4547 (::__interception::uptr)&TRAMPOLINE(func))
4648#else
4749#define INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) \
lib/tsan/interception/interception_win.cpp+56-27
......@@ -1,4 +1,4 @@
1//===-- interception_linux.cpp ----------------------------------*- C++ -*-===//
1//===-- interception_win.cpp ------------------------------------*- C++ -*-===//
22//
33// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44// See https://llvm.org/LICENSE.txt for license information.
......@@ -339,7 +339,7 @@ struct TrampolineMemoryRegion {
339339 uptr max_size;
340340};
341341
342UNUSED static const uptr kTrampolineScanLimitRange = 1 << 31; // 2 gig
342UNUSED static const uptr kTrampolineScanLimitRange = 1ull << 31; // 2 gig
343343static const int kMaxTrampolineRegion = 1024;
344344static TrampolineMemoryRegion TrampolineRegions[kMaxTrampolineRegion];
345345
......@@ -431,7 +431,8 @@ static uptr AllocateMemoryForTrampoline(uptr image_address, size_t size) {
431431// The following prologues cannot be patched because of the short jump
432432// jumping to the patching region.
433433
434#if SANITIZER_WINDOWS64
434// Short jump patterns below are only for x86_64.
435# if SANITIZER_WINDOWS_x64
435436// ntdll!wcslen in Win11
436437// 488bc1 mov rax,rcx
437438// 0fb710 movzx edx,word ptr [rax]
......@@ -457,7 +458,12 @@ static const u8 kPrologueWithShortJump2[] = {
457458
458459// Returns 0 on error.
459460static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
460#if SANITIZER_WINDOWS64
461#if SANITIZER_ARM64
462 // An ARM64 instruction is 4 bytes long.
463 return 4;
464#endif
465
466# if SANITIZER_WINDOWS_x64
461467 if (memcmp((u8*)address, kPrologueWithShortJump1,
462468 sizeof(kPrologueWithShortJump1)) == 0 ||
463469 memcmp((u8*)address, kPrologueWithShortJump2,
......@@ -473,6 +479,8 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
473479
474480 switch (*(u8*)address) {
475481 case 0x90: // 90 : nop
482 case 0xC3: // C3 : ret (for small/empty function interception
483 case 0xCC: // CC : int 3 i.e. registering weak functions)
476484 return 1;
477485
478486 case 0x50: // push eax / rax
......@@ -496,7 +504,6 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
496504 // Cannot overwrite control-instruction. Return 0 to indicate failure.
497505 case 0xE9: // E9 XX XX XX XX : jmp <label>
498506 case 0xE8: // E8 XX XX XX XX : call <func>
499 case 0xC3: // C3 : ret
500507 case 0xEB: // EB XX : jmp XX (short jump)
501508 case 0x70: // 7Y YY : jy XX (short conditional jump)
502509 case 0x71:
......@@ -539,7 +546,12 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
539546 return 7;
540547 }
541548
542#if SANITIZER_WINDOWS64
549 switch (0x000000FF & *(u32 *)address) {
550 case 0xc2: // C2 XX XX : ret XX (needed for registering weak functions)
551 return 3;
552 }
553
554# if SANITIZER_WINDOWS_x64
543555 switch (*(u8*)address) {
544556 case 0xA1: // A1 XX XX XX XX XX XX XX XX :
545557 // movabs eax, dword ptr ds:[XXXXXXXX]
......@@ -572,6 +584,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
572584 case 0x018a: // mov al, byte ptr [rcx]
573585 return 2;
574586
587 case 0x058A: // 8A 05 XX XX XX XX : mov al, byte ptr [XX XX XX XX]
575588 case 0x058B: // 8B 05 XX XX XX XX : mov eax, dword ptr [XX XX XX XX]
576589 if (rel_offset)
577590 *rel_offset = 2;
......@@ -598,6 +611,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
598611 case 0xc18b4c: // 4C 8B C1 : mov r8, rcx
599612 case 0xd2b60f: // 0f b6 d2 : movzx edx, dl
600613 case 0xca2b48: // 48 2b ca : sub rcx, rdx
614 case 0xca3b48: // 48 3b ca : cmp rcx, rdx
601615 case 0x10b70f: // 0f b7 10 : movzx edx, WORD PTR [rax]
602616 case 0xc00b4d: // 3d 0b c0 : or r8, r8
603617 case 0xc08b41: // 41 8b c0 : mov eax, r8d
......@@ -617,9 +631,11 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
617631
618632 case 0x058b48: // 48 8b 05 XX XX XX XX :
619633 // mov rax, QWORD PTR [rip + XXXXXXXX]
634 case 0x058d48: // 48 8d 05 XX XX XX XX :
635 // lea rax, QWORD PTR [rip + XXXXXXXX]
620636 case 0x25ff48: // 48 ff 25 XX XX XX XX :
621637 // rex.W jmp QWORD PTR [rip + XXXXXXXX]
622
638 case 0x158D4C: // 4c 8d 15 XX XX XX XX : lea r10, [rip + XX]
623639 // Instructions having offset relative to 'rip' need offset adjustment.
624640 if (rel_offset)
625641 *rel_offset = 3;
......@@ -721,16 +737,22 @@ static bool CopyInstructions(uptr to, uptr from, size_t size) {
721737 size_t instruction_size = GetInstructionSize(from + cursor, &rel_offset);
722738 if (!instruction_size)
723739 return false;
724 _memcpy((void*)(to + cursor), (void*)(from + cursor),
740 _memcpy((void *)(to + cursor), (void *)(from + cursor),
725741 (size_t)instruction_size);
726742 if (rel_offset) {
727 uptr delta = to - from;
728 uptr relocated_offset = *(u32*)(to + cursor + rel_offset) - delta;
729#if SANITIZER_WINDOWS64
730 if (relocated_offset + 0x80000000U >= 0xFFFFFFFFU)
743# if SANITIZER_WINDOWS64
744 // we want to make sure that the new relative offset still fits in 32-bits
745 // this will be untrue if relocated_offset \notin [-2**31, 2**31)
746 s64 delta = to - from;
747 s64 relocated_offset = *(s32 *)(to + cursor + rel_offset) - delta;
748 if (-0x8000'0000ll > relocated_offset || relocated_offset > 0x7FFF'FFFFll)
731749 return false;
732#endif
733 *(u32*)(to + cursor + rel_offset) = relocated_offset;
750# else
751 // on 32-bit, the relative offset will always be correct
752 s32 delta = to - from;
753 s32 relocated_offset = *(s32 *)(to + cursor + rel_offset) - delta;
754# endif
755 *(s32 *)(to + cursor + rel_offset) = relocated_offset;
734756 }
735757 cursor += instruction_size;
736758 }
......@@ -932,19 +954,26 @@ bool OverrideFunction(
932954
933955static void **InterestingDLLsAvailable() {
934956 static const char *InterestingDLLs[] = {
935 "kernel32.dll",
936 "msvcr100.dll", // VS2010
937 "msvcr110.dll", // VS2012
938 "msvcr120.dll", // VS2013
939 "vcruntime140.dll", // VS2015
940 "ucrtbase.dll", // Universal CRT
941#if (defined(__MINGW32__) && defined(__i386__))
942 "libc++.dll", // libc++
943 "libunwind.dll", // libunwind
944#endif
945 // NTDLL should go last as it exports some functions that we should
946 // override in the CRT [presumably only used internally].
947 "ntdll.dll", NULL};
957 "kernel32.dll",
958 "msvcr100d.dll", // VS2010
959 "msvcr110d.dll", // VS2012
960 "msvcr120d.dll", // VS2013
961 "vcruntime140d.dll", // VS2015
962 "ucrtbased.dll", // Universal CRT
963 "msvcr100.dll", // VS2010
964 "msvcr110.dll", // VS2012
965 "msvcr120.dll", // VS2013
966 "vcruntime140.dll", // VS2015
967 "ucrtbase.dll", // Universal CRT
968# if (defined(__MINGW32__) && defined(__i386__))
969 "libc++.dll", // libc++
970 "libunwind.dll", // libunwind
971# endif
972 // NTDLL should go last as it exports some functions that we should
973 // override in the CRT [presumably only used internally].
974 "ntdll.dll",
975 NULL
976 };
948977 static void *result[ARRAY_SIZE(InterestingDLLs)] = { 0 };
949978 if (!result[0]) {
950979 for (size_t i = 0, j = 0; InterestingDLLs[i]; ++i) {
lib/tsan/sanitizer_common/sanitizer_allocator.cpp+8-2
......@@ -25,7 +25,7 @@ namespace __sanitizer {
2525const char *PrimaryAllocatorName = "SizeClassAllocator";
2626const char *SecondaryAllocatorName = "LargeMmapAllocator";
2727
28static ALIGNED(64) char internal_alloc_placeholder[sizeof(InternalAllocator)];
28alignas(64) static char internal_alloc_placeholder[sizeof(InternalAllocator)];
2929static atomic_uint8_t internal_allocator_initialized;
3030static StaticSpinMutex internal_alloc_init_mu;
3131
......@@ -138,14 +138,20 @@ void InternalAllocatorUnlock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
138138
139139// LowLevelAllocator
140140constexpr uptr kLowLevelAllocatorDefaultAlignment = 8;
141constexpr uptr kMinNumPagesRounded = 16;
142constexpr uptr kMinRoundedSize = 65536;
141143static uptr low_level_alloc_min_alignment = kLowLevelAllocatorDefaultAlignment;
142144static LowLevelAllocateCallback low_level_alloc_callback;
143145
146static LowLevelAllocator Alloc;
147LowLevelAllocator &GetGlobalLowLevelAllocator() { return Alloc; }
148
144149void *LowLevelAllocator::Allocate(uptr size) {
145150 // Align allocation size.
146151 size = RoundUpTo(size, low_level_alloc_min_alignment);
147152 if (allocated_end_ - allocated_current_ < (sptr)size) {
148 uptr size_to_allocate = RoundUpTo(size, GetPageSizeCached());
153 uptr size_to_allocate = RoundUpTo(
154 size, Min(GetPageSizeCached() * kMinNumPagesRounded, kMinRoundedSize));
149155 allocated_current_ = (char *)MmapOrDie(size_to_allocate, __func__);
150156 allocated_end_ = allocated_current_ + size_to_allocate;
151157 if (low_level_alloc_callback) {
lib/tsan/sanitizer_common/sanitizer_allocator_interface.h+2
......@@ -40,6 +40,8 @@ SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
4040 void __sanitizer_malloc_hook(void *ptr, uptr size);
4141SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
4242 void __sanitizer_free_hook(void *ptr);
43SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE int
44__sanitizer_ignore_free_hook(void *ptr);
4345
4446SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
4547__sanitizer_purge_allocator();
lib/tsan/sanitizer_common/sanitizer_allocator_primary32.h+1-1
......@@ -278,7 +278,7 @@ class SizeClassAllocator32 {
278278 static const uptr kRegionSize = 1 << kRegionSizeLog;
279279 static const uptr kNumPossibleRegions = kSpaceSize / kRegionSize;
280280
281 struct ALIGNED(SANITIZER_CACHE_LINE_SIZE) SizeClassInfo {
281 struct alignas(SANITIZER_CACHE_LINE_SIZE) SizeClassInfo {
282282 StaticSpinMutex mutex;
283283 IntrusiveList<TransferBatch> free_list;
284284 u32 rand_state;
lib/tsan/sanitizer_common/sanitizer_allocator_primary64.h+9-7
......@@ -316,13 +316,13 @@ class SizeClassAllocator64 {
316316 Printf(
317317 "%s %02zd (%6zd): mapped: %6zdK allocs: %7zd frees: %7zd inuse: %6zd "
318318 "num_freed_chunks %7zd avail: %6zd rss: %6zdK releases: %6zd "
319 "last released: %6lldK region: 0x%zx\n",
319 "last released: %6lldK region: %p\n",
320320 region->exhausted ? "F" : " ", class_id, ClassIdToSize(class_id),
321321 region->mapped_user >> 10, region->stats.n_allocated,
322322 region->stats.n_freed, in_use, region->num_freed_chunks, avail_chunks,
323323 rss >> 10, region->rtoi.num_releases,
324324 region->rtoi.last_released_bytes >> 10,
325 SpaceBeg() + kRegionSize * class_id);
325 (void *)(SpaceBeg() + kRegionSize * class_id));
326326 }
327327
328328 void PrintStats() {
......@@ -636,15 +636,17 @@ class SizeClassAllocator64 {
636636 }
637637 uptr SpaceEnd() const { return SpaceBeg() + kSpaceSize; }
638638 // kRegionSize should be able to satisfy the largest size class.
639 static_assert(kRegionSize >= SizeClassMap::kMaxSize);
639 static_assert(kRegionSize >= SizeClassMap::kMaxSize,
640 "Region size exceed largest size");
640641 // kRegionSize must be <= 2^36, see CompactPtrT.
641 COMPILER_CHECK((kRegionSize) <= (1ULL << (SANITIZER_WORDSIZE / 2 + 4)));
642 COMPILER_CHECK((kRegionSize) <=
643 (1ULL << (sizeof(CompactPtrT) * 8 + kCompactPtrScale)));
642644 // Call mmap for user memory with at least this size.
643 static const uptr kUserMapSize = 1 << 16;
645 static const uptr kUserMapSize = 1 << 18;
644646 // Call mmap for metadata memory with at least this size.
645647 static const uptr kMetaMapSize = 1 << 16;
646648 // Call mmap for free array memory with at least this size.
647 static const uptr kFreeArrayMapSize = 1 << 16;
649 static const uptr kFreeArrayMapSize = 1 << 18;
648650
649651 atomic_sint32_t release_to_os_interval_ms_;
650652
......@@ -665,7 +667,7 @@ class SizeClassAllocator64 {
665667 u64 last_released_bytes;
666668 };
667669
668 struct ALIGNED(SANITIZER_CACHE_LINE_SIZE) RegionInfo {
670 struct alignas(SANITIZER_CACHE_LINE_SIZE) RegionInfo {
669671 Mutex mutex;
670672 uptr num_freed_chunks; // Number of elements in the freearray.
671673 uptr mapped_free_array; // Bytes mapped for freearray.
lib/tsan/sanitizer_common/sanitizer_asm.h+40-3
......@@ -42,6 +42,16 @@
4242# define CFI_RESTORE(reg)
4343#endif
4444
45#if defined(__aarch64__) && defined(__ARM_FEATURE_BTI_DEFAULT)
46# define ASM_STARTPROC CFI_STARTPROC; hint #34
47# define C_ASM_STARTPROC SANITIZER_STRINGIFY(CFI_STARTPROC) "\nhint #34"
48#else
49# define ASM_STARTPROC CFI_STARTPROC
50# define C_ASM_STARTPROC SANITIZER_STRINGIFY(CFI_STARTPROC)
51#endif
52#define ASM_ENDPROC CFI_ENDPROC
53#define C_ASM_ENDPROC SANITIZER_STRINGIFY(CFI_ENDPROC)
54
4555#if defined(__x86_64__) || defined(__i386__) || defined(__sparc__)
4656# define ASM_TAIL_CALL jmp
4757#elif defined(__arm__) || defined(__aarch64__) || defined(__mips__) || \
......@@ -53,6 +63,29 @@
5363# define ASM_TAIL_CALL tail
5464#endif
5565
66// Currently, almost all of the shared libraries rely on the value of
67// $t9 to get the address of current function, instead of PCREL, even
68// on MIPSr6. To be compatiable with them, we have to set $t9 properly.
69// MIPS uses GOT to get the address of preemptible functions.
70#if defined(__mips64)
71# define C_ASM_TAIL_CALL(t_func, i_func) \
72 "lui $t8, %hi(%neg(%gp_rel(" t_func ")))\n" \
73 "daddu $t8, $t8, $t9\n" \
74 "daddiu $t8, $t8, %lo(%neg(%gp_rel(" t_func ")))\n" \
75 "ld $t9, %got_disp(" i_func ")($t8)\n" \
76 "jr $t9\n"
77#elif defined(__mips__)
78# define C_ASM_TAIL_CALL(t_func, i_func) \
79 ".set noreorder\n" \
80 ".cpload $t9\n" \
81 ".set reorder\n" \
82 "lw $t9, %got(" i_func ")($gp)\n" \
83 "jr $t9\n"
84#elif defined(ASM_TAIL_CALL)
85# define C_ASM_TAIL_CALL(t_func, i_func) \
86 SANITIZER_STRINGIFY(ASM_TAIL_CALL) " " i_func
87#endif
88
5689#if defined(__ELF__) && defined(__x86_64__) || defined(__i386__) || \
5790 defined(__riscv)
5891# define ASM_PREEMPTIBLE_SYM(sym) sym@plt
......@@ -62,7 +95,11 @@
6295
6396#if !defined(__APPLE__)
6497# define ASM_HIDDEN(symbol) .hidden symbol
65# define ASM_TYPE_FUNCTION(symbol) .type symbol, %function
98# if defined(__arm__) || defined(__aarch64__)
99# define ASM_TYPE_FUNCTION(symbol) .type symbol, %function
100# else
101# define ASM_TYPE_FUNCTION(symbol) .type symbol, @function
102# endif
66103# define ASM_SIZE(symbol) .size symbol, .-symbol
67104# define ASM_SYMBOL(symbol) symbol
68105# define ASM_SYMBOL_INTERCEPTOR(symbol) symbol
......@@ -87,9 +124,9 @@
87124 .globl __interceptor_trampoline_##name; \
88125 ASM_TYPE_FUNCTION(__interceptor_trampoline_##name); \
89126 __interceptor_trampoline_##name: \
90 CFI_STARTPROC; \
127 ASM_STARTPROC; \
91128 ASM_TAIL_CALL ASM_PREEMPTIBLE_SYM(__interceptor_##name); \
92 CFI_ENDPROC; \
129 ASM_ENDPROC; \
93130 ASM_SIZE(__interceptor_trampoline_##name)
94131# define ASM_INTERCEPTOR_TRAMPOLINE_SUPPORT 1
95132# endif // Architecture supports interceptor trampoline
lib/tsan/sanitizer_common/sanitizer_atomic.h+13-1
......@@ -18,12 +18,24 @@
1818namespace __sanitizer {
1919
2020enum memory_order {
21// If the __atomic atomic builtins are supported (Clang/GCC), use the
22// compiler provided macro values so that we can map the atomic operations
23// to __atomic_* directly.
24#ifdef __ATOMIC_SEQ_CST
25 memory_order_relaxed = __ATOMIC_RELAXED,
26 memory_order_consume = __ATOMIC_CONSUME,
27 memory_order_acquire = __ATOMIC_ACQUIRE,
28 memory_order_release = __ATOMIC_RELEASE,
29 memory_order_acq_rel = __ATOMIC_ACQ_REL,
30 memory_order_seq_cst = __ATOMIC_SEQ_CST
31#else
2132 memory_order_relaxed = 1 << 0,
2233 memory_order_consume = 1 << 1,
2334 memory_order_acquire = 1 << 2,
2435 memory_order_release = 1 << 3,
2536 memory_order_acq_rel = 1 << 4,
2637 memory_order_seq_cst = 1 << 5
38#endif
2739};
2840
2941struct atomic_uint8_t {
......@@ -49,7 +61,7 @@ struct atomic_uint32_t {
4961struct atomic_uint64_t {
5062 typedef u64 Type;
5163 // On 32-bit platforms u64 is not necessary aligned on 8 bytes.
52 volatile ALIGNED(8) Type val_dont_use;
64 alignas(8) volatile Type val_dont_use;
5365};
5466
5567struct atomic_uintptr_t {
lib/tsan/sanitizer_common/sanitizer_atomic_clang.h+40-45
......@@ -14,60 +14,63 @@
1414#ifndef SANITIZER_ATOMIC_CLANG_H
1515#define SANITIZER_ATOMIC_CLANG_H
1616
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
2317namespace __sanitizer {
2418
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'
19// We use the compiler builtin atomic operations for loads and stores, which
20// generates correct code for all architectures, but may require libatomic
21// on platforms where e.g. 64-bit atomics are not supported natively.
3322
3423// See http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html
3524// for mappings of the memory model to different processors.
3625
37inline void atomic_signal_fence(memory_order) {
26inline void atomic_signal_fence(memory_order mo) { __atomic_signal_fence(mo); }
27
28inline void atomic_thread_fence(memory_order mo) { __atomic_thread_fence(mo); }
29
30inline void proc_yield(int cnt) {
31 __asm__ __volatile__("" ::: "memory");
32#if defined(__i386__) || defined(__x86_64__)
33 for (int i = 0; i < cnt; i++) __asm__ __volatile__("pause");
3834 __asm__ __volatile__("" ::: "memory");
35#endif
3936}
4037
41inline void atomic_thread_fence(memory_order) {
42 __sync_synchronize();
38template <typename T>
39inline typename T::Type atomic_load(const volatile T *a, memory_order mo) {
40 DCHECK(mo == memory_order_relaxed || mo == memory_order_consume ||
41 mo == memory_order_acquire || mo == memory_order_seq_cst);
42 DCHECK(!((uptr)a % sizeof(*a)));
43 return __atomic_load_n(&a->val_dont_use, mo);
4344}
4445
45template<typename T>
46inline typename T::Type atomic_fetch_add(volatile T *a,
47 typename T::Type v, memory_order mo) {
48 (void)mo;
46template <typename T>
47inline void atomic_store(volatile T *a, typename T::Type v, memory_order mo) {
48 DCHECK(mo == memory_order_relaxed || mo == memory_order_release ||
49 mo == memory_order_seq_cst);
4950 DCHECK(!((uptr)a % sizeof(*a)));
50 return __sync_fetch_and_add(&a->val_dont_use, v);
51 __atomic_store_n(&a->val_dont_use, v, mo);
5152}
5253
53template<typename T>
54inline typename T::Type atomic_fetch_sub(volatile T *a,
55 typename T::Type v, memory_order mo) {
54template <typename T>
55inline typename T::Type atomic_fetch_add(volatile T *a, typename T::Type v,
56 memory_order mo) {
57 DCHECK(!((uptr)a % sizeof(*a)));
58 return __atomic_fetch_add(&a->val_dont_use, v, mo);
59}
60
61template <typename T>
62inline typename T::Type atomic_fetch_sub(volatile T *a, typename T::Type v,
63 memory_order mo) {
5664 (void)mo;
5765 DCHECK(!((uptr)a % sizeof(*a)));
58 return __sync_fetch_and_add(&a->val_dont_use, -v);
66 return __atomic_fetch_sub(&a->val_dont_use, v, mo);
5967}
6068
61template<typename T>
62inline typename T::Type atomic_exchange(volatile T *a,
63 typename T::Type v, memory_order mo) {
69template <typename T>
70inline typename T::Type atomic_exchange(volatile T *a, typename T::Type v,
71 memory_order mo) {
6472 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;
73 return __atomic_exchange_n(&a->val_dont_use, v, mo);
7174}
7275
7376template <typename T>
......@@ -82,9 +85,8 @@ inline bool atomic_compare_exchange_strong(volatile T *a, typename T::Type *cmp,
8285 __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
8386}
8487
85template<typename T>
86inline bool atomic_compare_exchange_weak(volatile T *a,
87 typename T::Type *cmp,
88template <typename T>
89inline bool atomic_compare_exchange_weak(volatile T *a, typename T::Type *cmp,
8890 typename T::Type xchg,
8991 memory_order mo) {
9092 return atomic_compare_exchange_strong(a, cmp, xchg, mo);
......@@ -92,13 +94,6 @@ inline bool atomic_compare_exchange_weak(volatile T *a,
9294
9395} // namespace __sanitizer
9496
95// This include provides explicit template instantiations for atomic_uint64_t
96// on MIPS32, which does not directly support 8 byte atomics. It has to
97// proceed the template definitions above.
98#if defined(_MIPS_SIM) && defined(_ABIO32) && _MIPS_SIM == _ABIO32
99# include "sanitizer_atomic_clang_mips.h"
100#endif
101
10297#undef ATOMIC_ORDER
10398
10499#endif // SANITIZER_ATOMIC_CLANG_H
lib/tsan/sanitizer_common/sanitizer_atomic_clang_mips.h deleted-117
......@@ -1,117 +0,0 @@
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 operations 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_release | 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_release | 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_release | 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_release | 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 deleted-85
......@@ -1,85 +0,0 @@
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 __atomic_load(const_cast<typename T::Type volatile *>(&a->val_dont_use), &v,
54 __ATOMIC_SEQ_CST);
55 }
56 return v;
57}
58
59template<typename T>
60inline void atomic_store(volatile T *a, typename T::Type v, memory_order mo) {
61 DCHECK(mo & (memory_order_relaxed | memory_order_release
62 | memory_order_seq_cst));
63 DCHECK(!((uptr)a % sizeof(*a)));
64
65 if (sizeof(*a) < 8 || sizeof(void*) == 8) {
66 // Assume that aligned loads are atomic.
67 if (mo == memory_order_relaxed) {
68 a->val_dont_use = v;
69 } else if (mo == memory_order_release) {
70 __sync_synchronize();
71 a->val_dont_use = v;
72 __asm__ __volatile__("" ::: "memory");
73 } else { // seq_cst
74 __sync_synchronize();
75 a->val_dont_use = v;
76 __sync_synchronize();
77 }
78 } else {
79 __atomic_store(&a->val_dont_use, &v, __ATOMIC_SEQ_CST);
80 }
81}
82
83} // namespace __sanitizer
84
85#endif // #ifndef SANITIZER_ATOMIC_CLANG_OTHER_H
lib/tsan/sanitizer_common/sanitizer_atomic_clang_x86.h deleted-113
......@@ -1,113 +0,0 @@
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+4-4
......@@ -70,8 +70,8 @@ inline void proc_yield(int cnt) {
7070template<typename T>
7171inline typename T::Type atomic_load(
7272 const volatile T *a, memory_order mo) {
73 DCHECK(mo & (memory_order_relaxed | memory_order_consume
74 | memory_order_acquire | memory_order_seq_cst));
73 DCHECK(mo == memory_order_relaxed || mo == memory_order_consume ||
74 mo == memory_order_acquire || mo == memory_order_seq_cst);
7575 DCHECK(!((uptr)a % sizeof(*a)));
7676 typename T::Type v;
7777 // FIXME(dvyukov): 64-bit load is not atomic on 32-bits.
......@@ -87,8 +87,8 @@ inline typename T::Type atomic_load(
8787
8888template<typename T>
8989inline 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));
90 DCHECK(mo == memory_order_relaxed || mo == memory_order_release ||
91 mo == memory_order_seq_cst);
9292 DCHECK(!((uptr)a % sizeof(*a)));
9393 // FIXME(dvyukov): 64-bit store is not atomic on 32-bits.
9494 if (mo == memory_order_relaxed) {
lib/tsan/sanitizer_common/sanitizer_bitvector.h+4-4
......@@ -321,23 +321,23 @@ class TwoLevelBitVector {
321321 };
322322
323323 private:
324 void check(uptr idx) const { CHECK_LE(idx, size()); }
324 void check(uptr idx) const { CHECK_LT(idx, size()); }
325325
326326 uptr idx0(uptr idx) const {
327327 uptr res = idx / (BV::kSize * BV::kSize);
328 CHECK_LE(res, kLevel1Size);
328 CHECK_LT(res, kLevel1Size);
329329 return res;
330330 }
331331
332332 uptr idx1(uptr idx) const {
333333 uptr res = (idx / BV::kSize) % BV::kSize;
334 CHECK_LE(res, BV::kSize);
334 CHECK_LT(res, BV::kSize);
335335 return res;
336336 }
337337
338338 uptr idx2(uptr idx) const {
339339 uptr res = idx % BV::kSize;
340 CHECK_LE(res, BV::kSize);
340 CHECK_LT(res, BV::kSize);
341341 return res;
342342 }
343343
lib/tsan/sanitizer_common/sanitizer_chained_origin_depot.cpp+4-2
......@@ -139,9 +139,11 @@ u32 ChainedOriginDepot::Get(u32 id, u32 *other) {
139139 return desc.here_id;
140140}
141141
142void ChainedOriginDepot::LockAll() { depot.LockAll(); }
142void ChainedOriginDepot::LockBeforeFork() { depot.LockBeforeFork(); }
143143
144void ChainedOriginDepot::UnlockAll() { depot.UnlockAll(); }
144void ChainedOriginDepot::UnlockAfterFork(bool fork_child) {
145 depot.UnlockAfterFork(fork_child);
146}
145147
146148void ChainedOriginDepot::TestOnlyUnmap() { depot.TestOnlyUnmap(); }
147149
lib/tsan/sanitizer_common/sanitizer_chained_origin_depot.h+2-2
......@@ -32,8 +32,8 @@ class ChainedOriginDepot {
3232 // Retrieves the stored StackDepot ID for the given origin ID.
3333 u32 Get(u32 id, u32 *other);
3434
35 void LockAll();
36 void UnlockAll();
35 void LockBeforeFork();
36 void UnlockAfterFork(bool fork_child);
3737 void TestOnlyUnmap();
3838
3939 private:
lib/tsan/sanitizer_common/sanitizer_common.cpp+17-3
......@@ -115,8 +115,9 @@ void ReportErrorSummary(const char *error_message, const char *alt_tool_name) {
115115 if (!common_flags()->print_summary)
116116 return;
117117 InternalScopedString buff;
118 buff.append("SUMMARY: %s: %s",
119 alt_tool_name ? alt_tool_name : SanitizerToolName, error_message);
118 buff.AppendF("SUMMARY: %s: %s",
119 alt_tool_name ? alt_tool_name : SanitizerToolName,
120 error_message);
120121 __sanitizer_report_error_summary(buff.data());
121122}
122123
......@@ -346,7 +347,13 @@ void RunMallocHooks(void *ptr, uptr size) {
346347 }
347348}
348349
349void RunFreeHooks(void *ptr) {
350// Returns '1' if the call to free() should be ignored (based on
351// __sanitizer_ignore_free_hook), or '0' otherwise.
352int RunFreeHooks(void *ptr) {
353 if (__sanitizer_ignore_free_hook(ptr)) {
354 return 1;
355 }
356
350357 __sanitizer_free_hook(ptr);
351358 for (int i = 0; i < kMaxMallocFreeHooks; i++) {
352359 auto hook = MFHooks[i].free_hook;
......@@ -354,6 +361,8 @@ void RunFreeHooks(void *ptr) {
354361 break;
355362 hook(ptr);
356363 }
364
365 return 0;
357366}
358367
359368static int InstallMallocFreeHooks(void (*malloc_hook)(const void *, uptr),
......@@ -418,4 +427,9 @@ SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_free_hook, void *ptr) {
418427 (void)ptr;
419428}
420429
430SANITIZER_INTERFACE_WEAK_DEF(int, __sanitizer_ignore_free_hook, void *ptr) {
431 (void)ptr;
432 return 0;
433}
434
421435} // extern "C"
lib/tsan/sanitizer_common/sanitizer_common.h+28-17
......@@ -32,6 +32,7 @@ struct AddressInfo;
3232struct BufferedStackTrace;
3333struct SignalContext;
3434struct StackTrace;
35struct SymbolizedStack;
3536
3637// Constants.
3738const uptr kWordSize = SANITIZER_WORDSIZE / 8;
......@@ -59,14 +60,10 @@ inline int Verbosity() {
5960 return atomic_load(&current_verbosity, memory_order_relaxed);
6061}
6162
62#if SANITIZER_ANDROID
63inline uptr GetPageSize() {
64// Android post-M sysconf(_SC_PAGESIZE) crashes if called from .preinit_array.
65 return 4096;
66}
67inline uptr GetPageSizeCached() {
68 return 4096;
69}
63#if SANITIZER_ANDROID && !defined(__aarch64__)
64// 32-bit Android only has 4k pages.
65inline uptr GetPageSize() { return 4096; }
66inline uptr GetPageSizeCached() { return 4096; }
7067#else
7168uptr GetPageSize();
7269extern uptr PageSizeCached;
......@@ -76,6 +73,7 @@ inline uptr GetPageSizeCached() {
7673 return PageSizeCached;
7774}
7875#endif
76
7977uptr GetMmapGranularity();
8078uptr GetMaxVirtualAddress();
8179uptr GetMaxUserVirtualAddress();
......@@ -90,10 +88,11 @@ void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
9088
9189// Memory management
9290void *MmapOrDie(uptr size, const char *mem_type, bool raw_report = false);
91
9392inline void *MmapOrDieQuietly(uptr size, const char *mem_type) {
9493 return MmapOrDie(size, mem_type, /*raw_report*/ true);
9594}
96void UnmapOrDie(void *addr, uptr size);
95void UnmapOrDie(void *addr, uptr size, bool raw_report = false);
9796// Behaves just like MmapOrDie, but tolerates out of memory condition, in that
9897// case returns nullptr.
9998void *MmapOrDieOnFatalError(uptr size, const char *mem_type);
......@@ -138,7 +137,8 @@ void UnmapFromTo(uptr from, uptr to);
138137// shadow_size_bytes bytes on the right, which on linux is mapped no access.
139138// The high_mem_end may be updated if the original shadow size doesn't fit.
140139uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale,
141 uptr min_shadow_base_alignment, uptr &high_mem_end);
140 uptr min_shadow_base_alignment, uptr &high_mem_end,
141 uptr granularity);
142142
143143// Let S = max(shadow_size, num_aliases * alias_size, ring_buffer_size).
144144// Reserves 2*S bytes of address space to the right of the returned address and
......@@ -177,7 +177,7 @@ bool DontDumpShadowMemory(uptr addr, uptr length);
177177// Check if the built VMA size matches the runtime one.
178178void CheckVMASize();
179179void RunMallocHooks(void *ptr, uptr size);
180void RunFreeHooks(void *ptr);
180int RunFreeHooks(void *ptr);
181181
182182class ReservedAddressRange {
183183 public:
......@@ -208,6 +208,11 @@ void ParseUnixMemoryProfile(fill_profile_f cb, uptr *stats, char *smaps,
208208// Simple low-level (mmap-based) allocator for internal use. Doesn't have
209209// constructor, so all instances of LowLevelAllocator should be
210210// linker initialized.
211//
212// NOTE: Users should instead use the singleton provided via
213// `GetGlobalLowLevelAllocator()` rather than create a new one. This way, the
214// number of mmap fragments can be reduced and use the same contiguous mmap
215// provided by this singleton.
211216class LowLevelAllocator {
212217 public:
213218 // Requires an external lock.
......@@ -224,6 +229,8 @@ typedef void (*LowLevelAllocateCallback)(uptr ptr, uptr size);
224229// Passing NULL removes the callback.
225230void SetLowLevelAllocateCallback(LowLevelAllocateCallback callback);
226231
232LowLevelAllocator &GetGlobalLowLevelAllocator();
233
227234// IO
228235void CatastrophicErrorWrite(const char *buffer, uptr length);
229236void RawWrite(const char *buffer);
......@@ -386,6 +393,8 @@ void ReportErrorSummary(const char *error_type, const AddressInfo &info,
386393// Same as above, but obtains AddressInfo by symbolizing top stack trace frame.
387394void ReportErrorSummary(const char *error_type, const StackTrace *trace,
388395 const char *alt_tool_name = nullptr);
396// Skips frames which we consider internal and not usefull to the users.
397const SymbolizedStack *SkipInternalFrames(const SymbolizedStack *frames);
389398
390399void ReportMmapWriteExec(int prot, int mflags);
391400
......@@ -500,7 +509,7 @@ inline int ToLower(int c) {
500509// A low-level vector based on mmap. May incur a significant memory overhead for
501510// small vectors.
502511// WARNING: The current implementation supports only POD types.
503template<typename T>
512template <typename T, bool raw_report = false>
504513class InternalMmapVectorNoCtor {
505514 public:
506515 using value_type = T;
......@@ -510,7 +519,7 @@ class InternalMmapVectorNoCtor {
510519 data_ = 0;
511520 reserve(initial_capacity);
512521 }
513 void Destroy() { UnmapOrDie(data_, capacity_bytes_); }
522 void Destroy() { UnmapOrDie(data_, capacity_bytes_, raw_report); }
514523 T &operator[](uptr i) {
515524 CHECK_LT(i, size_);
516525 return data_[i];
......@@ -586,9 +595,10 @@ class InternalMmapVectorNoCtor {
586595 CHECK_LE(size_, new_capacity);
587596 uptr new_capacity_bytes =
588597 RoundUpTo(new_capacity * sizeof(T), GetPageSizeCached());
589 T *new_data = (T *)MmapOrDie(new_capacity_bytes, "InternalMmapVector");
598 T *new_data =
599 (T *)MmapOrDie(new_capacity_bytes, "InternalMmapVector", raw_report);
590600 internal_memcpy(new_data, data_, size_ * sizeof(T));
591 UnmapOrDie(data_, capacity_bytes_);
601 UnmapOrDie(data_, capacity_bytes_, raw_report);
592602 data_ = new_data;
593603 capacity_bytes_ = new_capacity_bytes;
594604 }
......@@ -636,7 +646,8 @@ class InternalScopedString {
636646 buffer_.resize(1);
637647 buffer_[0] = '\0';
638648 }
639 void append(const char *format, ...) FORMAT(2, 3);
649 void Append(const char *str);
650 void AppendF(const char *format, ...) FORMAT(2, 3);
640651 const char *data() const { return buffer_.data(); }
641652 char *data() { return buffer_.data(); }
642653
......@@ -1086,7 +1097,7 @@ inline u32 GetNumberOfCPUsCached() {
10861097
10871098} // namespace __sanitizer
10881099
1089inline void *operator new(__sanitizer::operator_new_size_type size,
1100inline void *operator new(__sanitizer::usize size,
10901101 __sanitizer::LowLevelAllocator &alloc) {
10911102 return alloc.Allocate(size);
10921103}
lib/tsan/sanitizer_common/sanitizer_common_interceptors.inc+137-66
......@@ -33,16 +33,17 @@
3333// COMMON_INTERCEPTOR_STRERROR
3434//===----------------------------------------------------------------------===//
3535
36#include <stdarg.h>
37
3638#include "interception/interception.h"
3739#include "sanitizer_addrhashmap.h"
40#include "sanitizer_dl.h"
3841#include "sanitizer_errno.h"
3942#include "sanitizer_placement_new.h"
4043#include "sanitizer_platform_interceptors.h"
4144#include "sanitizer_symbolizer.h"
4245#include "sanitizer_tls_get_addr.h"
4346
44#include <stdarg.h>
45
4647#if SANITIZER_INTERCEPTOR_HOOKS
4748#define CALL_WEAK_INTERCEPTOR_HOOK(f, ...) f(__VA_ARGS__);
4849#define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...) \
......@@ -445,11 +446,13 @@ INTERCEPTOR(char*, textdomain, const char *domainname) {
445446#define INIT_TEXTDOMAIN
446447#endif
447448
448#if SANITIZER_INTERCEPT_STRCMP
449#if SANITIZER_INTERCEPT_STRCMP || SANITIZER_INTERCEPT_MEMCMP
449450static inline int CharCmpX(unsigned char c1, unsigned char c2) {
450451 return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
451452}
453#endif
452454
455#if SANITIZER_INTERCEPT_STRCMP
453456DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcmp, uptr called_pc,
454457 const char *s1, const char *s2, int result)
455458
......@@ -971,7 +974,7 @@ INTERCEPTOR(SSIZE_T, read, int fd, void *ptr, SIZE_T count) {
971974 // FIXME: under ASan the call below may write to freed memory and corrupt
972975 // its metadata. See
973976 // https://github.com/google/sanitizers/issues/321.
974 SSIZE_T res = REAL(read)(fd, ptr, count);
977 SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(read)(fd, ptr, count);
975978 if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
976979 if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
977980 return res;
......@@ -1006,7 +1009,7 @@ INTERCEPTOR(SSIZE_T, pread, int fd, void *ptr, SIZE_T count, OFF_T offset) {
10061009 // FIXME: under ASan the call below may write to freed memory and corrupt
10071010 // its metadata. See
10081011 // https://github.com/google/sanitizers/issues/321.
1009 SSIZE_T res = REAL(pread)(fd, ptr, count, offset);
1012 SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(pread)(fd, ptr, count, offset);
10101013 if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
10111014 if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
10121015 return res;
......@@ -1024,7 +1027,7 @@ INTERCEPTOR(SSIZE_T, pread64, int fd, void *ptr, SIZE_T count, OFF64_T offset) {
10241027 // FIXME: under ASan the call below may write to freed memory and corrupt
10251028 // its metadata. See
10261029 // https://github.com/google/sanitizers/issues/321.
1027 SSIZE_T res = REAL(pread64)(fd, ptr, count, offset);
1030 SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(pread64)(fd, ptr, count, offset);
10281031 if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
10291032 if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
10301033 return res;
......@@ -1040,7 +1043,7 @@ INTERCEPTOR_WITH_SUFFIX(SSIZE_T, readv, int fd, __sanitizer_iovec *iov,
10401043 void *ctx;
10411044 COMMON_INTERCEPTOR_ENTER(ctx, readv, fd, iov, iovcnt);
10421045 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
1043 SSIZE_T res = REAL(readv)(fd, iov, iovcnt);
1046 SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(readv)(fd, iov, iovcnt);
10441047 if (res > 0) write_iovec(ctx, iov, iovcnt, res);
10451048 if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
10461049 return res;
......@@ -1056,7 +1059,7 @@ INTERCEPTOR(SSIZE_T, preadv, int fd, __sanitizer_iovec *iov, int iovcnt,
10561059 void *ctx;
10571060 COMMON_INTERCEPTOR_ENTER(ctx, preadv, fd, iov, iovcnt, offset);
10581061 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
1059 SSIZE_T res = REAL(preadv)(fd, iov, iovcnt, offset);
1062 SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(preadv)(fd, iov, iovcnt, offset);
10601063 if (res > 0) write_iovec(ctx, iov, iovcnt, res);
10611064 if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
10621065 return res;
......@@ -1072,7 +1075,8 @@ INTERCEPTOR(SSIZE_T, preadv64, int fd, __sanitizer_iovec *iov, int iovcnt,
10721075 void *ctx;
10731076 COMMON_INTERCEPTOR_ENTER(ctx, preadv64, fd, iov, iovcnt, offset);
10741077 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
1075 SSIZE_T res = REAL(preadv64)(fd, iov, iovcnt, offset);
1078 SSIZE_T res =
1079 COMMON_INTERCEPTOR_BLOCK_REAL(preadv64)(fd, iov, iovcnt, offset);
10761080 if (res > 0) write_iovec(ctx, iov, iovcnt, res);
10771081 if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
10781082 return res;
......@@ -1088,8 +1092,9 @@ INTERCEPTOR(SSIZE_T, write, int fd, void *ptr, SIZE_T count) {
10881092 COMMON_INTERCEPTOR_ENTER(ctx, write, fd, ptr, count);
10891093 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
10901094 if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
1091 SSIZE_T res = REAL(write)(fd, ptr, count);
1092 // FIXME: this check should be _before_ the call to REAL(write), not after
1095 SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(write)(fd, ptr, count);
1096 // FIXME: this check should be _before_ the call to
1097 // COMMON_INTERCEPTOR_BLOCK_REAL(write), not after
10931098 if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
10941099 return res;
10951100}
......@@ -1118,7 +1123,7 @@ INTERCEPTOR(SSIZE_T, pwrite, int fd, void *ptr, SIZE_T count, OFF_T offset) {
11181123 COMMON_INTERCEPTOR_ENTER(ctx, pwrite, fd, ptr, count, offset);
11191124 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
11201125 if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
1121 SSIZE_T res = REAL(pwrite)(fd, ptr, count, offset);
1126 SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(pwrite)(fd, ptr, count, offset);
11221127 if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
11231128 return res;
11241129}
......@@ -1134,7 +1139,7 @@ INTERCEPTOR(SSIZE_T, pwrite64, int fd, void *ptr, OFF64_T count,
11341139 COMMON_INTERCEPTOR_ENTER(ctx, pwrite64, fd, ptr, count, offset);
11351140 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
11361141 if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
1137 SSIZE_T res = REAL(pwrite64)(fd, ptr, count, offset);
1142 SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(pwrite64)(fd, ptr, count, offset);
11381143 if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
11391144 return res;
11401145}
......@@ -1150,7 +1155,7 @@ INTERCEPTOR_WITH_SUFFIX(SSIZE_T, writev, int fd, __sanitizer_iovec *iov,
11501155 COMMON_INTERCEPTOR_ENTER(ctx, writev, fd, iov, iovcnt);
11511156 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
11521157 if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
1153 SSIZE_T res = REAL(writev)(fd, iov, iovcnt);
1158 SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(writev)(fd, iov, iovcnt);
11541159 if (res > 0) read_iovec(ctx, iov, iovcnt, res);
11551160 return res;
11561161}
......@@ -1166,7 +1171,7 @@ INTERCEPTOR(SSIZE_T, pwritev, int fd, __sanitizer_iovec *iov, int iovcnt,
11661171 COMMON_INTERCEPTOR_ENTER(ctx, pwritev, fd, iov, iovcnt, offset);
11671172 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
11681173 if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
1169 SSIZE_T res = REAL(pwritev)(fd, iov, iovcnt, offset);
1174 SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(pwritev)(fd, iov, iovcnt, offset);
11701175 if (res > 0) read_iovec(ctx, iov, iovcnt, res);
11711176 return res;
11721177}
......@@ -1182,7 +1187,8 @@ INTERCEPTOR(SSIZE_T, pwritev64, int fd, __sanitizer_iovec *iov, int iovcnt,
11821187 COMMON_INTERCEPTOR_ENTER(ctx, pwritev64, fd, iov, iovcnt, offset);
11831188 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
11841189 if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
1185 SSIZE_T res = REAL(pwritev64)(fd, iov, iovcnt, offset);
1190 SSIZE_T res =
1191 COMMON_INTERCEPTOR_BLOCK_REAL(pwritev64)(fd, iov, iovcnt, offset);
11861192 if (res > 0) read_iovec(ctx, iov, iovcnt, res);
11871193 return res;
11881194}
......@@ -1245,6 +1251,7 @@ INTERCEPTOR(int, prctl, int option, unsigned long arg2, unsigned long arg3,
12451251 void *ctx;
12461252 COMMON_INTERCEPTOR_ENTER(ctx, prctl, option, arg2, arg3, arg4, arg5);
12471253 static const int PR_SET_NAME = 15;
1254 static const int PR_GET_NAME = 16;
12481255 static const int PR_SET_VMA = 0x53564d41;
12491256 static const int PR_SCHED_CORE = 62;
12501257 static const int PR_SCHED_CORE_GET = 0;
......@@ -1258,7 +1265,11 @@ INTERCEPTOR(int, prctl, int option, unsigned long arg2, unsigned long arg3,
12581265 internal_strncpy(buff, (char *)arg2, 15);
12591266 buff[15] = 0;
12601267 COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, buff);
1261 } else if (res != -1 && option == PR_SCHED_CORE && arg2 == PR_SCHED_CORE_GET) {
1268 } else if (res == 0 && option == PR_GET_NAME) {
1269 char *name = (char *)arg2;
1270 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strlen(name) + 1);
1271 } else if (res != -1 && option == PR_SCHED_CORE &&
1272 arg2 == PR_SCHED_CORE_GET) {
12621273 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (u64*)(arg5), sizeof(u64));
12631274 }
12641275 return res;
......@@ -2546,7 +2557,7 @@ INTERCEPTOR_WITH_SUFFIX(int, wait, int *status) {
25462557 // FIXME: under ASan the call below may write to freed memory and corrupt
25472558 // its metadata. See
25482559 // https://github.com/google/sanitizers/issues/321.
2549 int res = REAL(wait)(status);
2560 int res = COMMON_INTERCEPTOR_BLOCK_REAL(wait)(status);
25502561 if (res != -1 && status)
25512562 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
25522563 return res;
......@@ -2564,7 +2575,7 @@ INTERCEPTOR_WITH_SUFFIX(int, waitid, int idtype, int id, void *infop,
25642575 // FIXME: under ASan the call below may write to freed memory and corrupt
25652576 // its metadata. See
25662577 // https://github.com/google/sanitizers/issues/321.
2567 int res = REAL(waitid)(idtype, id, infop, options);
2578 int res = COMMON_INTERCEPTOR_BLOCK_REAL(waitid)(idtype, id, infop, options);
25682579 if (res != -1 && infop)
25692580 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, infop, siginfo_t_sz);
25702581 return res;
......@@ -2575,7 +2586,7 @@ INTERCEPTOR_WITH_SUFFIX(int, waitpid, int pid, int *status, int options) {
25752586 // FIXME: under ASan the call below may write to freed memory and corrupt
25762587 // its metadata. See
25772588 // https://github.com/google/sanitizers/issues/321.
2578 int res = REAL(waitpid)(pid, status, options);
2589 int res = COMMON_INTERCEPTOR_BLOCK_REAL(waitpid)(pid, status, options);
25792590 if (res != -1 && status)
25802591 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
25812592 return res;
......@@ -2586,7 +2597,7 @@ INTERCEPTOR(int, wait3, int *status, int options, void *rusage) {
25862597 // FIXME: under ASan the call below may write to freed memory and corrupt
25872598 // its metadata. See
25882599 // https://github.com/google/sanitizers/issues/321.
2589 int res = REAL(wait3)(status, options, rusage);
2600 int res = COMMON_INTERCEPTOR_BLOCK_REAL(wait3)(status, options, rusage);
25902601 if (res != -1) {
25912602 if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
25922603 if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
......@@ -2600,7 +2611,8 @@ INTERCEPTOR(int, __wait4, int pid, int *status, int options, void *rusage) {
26002611 // FIXME: under ASan the call below may write to freed memory and corrupt
26012612 // its metadata. See
26022613 // https://github.com/google/sanitizers/issues/321.
2603 int res = REAL(__wait4)(pid, status, options, rusage);
2614 int res =
2615 COMMON_INTERCEPTOR_BLOCK_REAL(__wait4)(pid, status, options, rusage);
26042616 if (res != -1) {
26052617 if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
26062618 if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
......@@ -2615,7 +2627,7 @@ INTERCEPTOR(int, wait4, int pid, int *status, int options, void *rusage) {
26152627 // FIXME: under ASan the call below may write to freed memory and corrupt
26162628 // its metadata. See
26172629 // https://github.com/google/sanitizers/issues/321.
2618 int res = REAL(wait4)(pid, status, options, rusage);
2630 int res = COMMON_INTERCEPTOR_BLOCK_REAL(wait4)(pid, status, options, rusage);
26192631 if (res != -1) {
26202632 if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
26212633 if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
......@@ -2993,7 +3005,7 @@ INTERCEPTOR(int, accept, int fd, void *addr, unsigned *addrlen) {
29933005 COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
29943006 addrlen0 = *addrlen;
29953007 }
2996 int fd2 = REAL(accept)(fd, addr, addrlen);
3008 int fd2 = COMMON_INTERCEPTOR_BLOCK_REAL(accept)(fd, addr, addrlen);
29973009 if (fd2 >= 0) {
29983010 if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
29993011 if (addr && addrlen)
......@@ -3018,7 +3030,7 @@ INTERCEPTOR(int, accept4, int fd, void *addr, unsigned *addrlen, int f) {
30183030 // FIXME: under ASan the call below may write to freed memory and corrupt
30193031 // its metadata. See
30203032 // https://github.com/google/sanitizers/issues/321.
3021 int fd2 = REAL(accept4)(fd, addr, addrlen, f);
3033 int fd2 = COMMON_INTERCEPTOR_BLOCK_REAL(accept4)(fd, addr, addrlen, f);
30223034 if (fd2 >= 0) {
30233035 if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
30243036 if (addr && addrlen)
......@@ -3042,7 +3054,7 @@ INTERCEPTOR(int, paccept, int fd, void *addr, unsigned *addrlen,
30423054 addrlen0 = *addrlen;
30433055 }
30443056 if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
3045 int fd2 = REAL(paccept)(fd, addr, addrlen, set, f);
3057 int fd2 = COMMON_INTERCEPTOR_BLOCK_REAL(paccept)(fd, addr, addrlen, set, f);
30463058 if (fd2 >= 0) {
30473059 if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
30483060 if (addr && addrlen)
......@@ -3123,7 +3135,7 @@ INTERCEPTOR(SSIZE_T, recvmsg, int fd, struct __sanitizer_msghdr *msg,
31233135 // FIXME: under ASan the call below may write to freed memory and corrupt
31243136 // its metadata. See
31253137 // https://github.com/google/sanitizers/issues/321.
3126 SSIZE_T res = REAL(recvmsg)(fd, msg, flags);
3138 SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(recvmsg)(fd, msg, flags);
31273139 if (res >= 0) {
31283140 if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
31293141 if (msg) {
......@@ -3144,7 +3156,8 @@ INTERCEPTOR(int, recvmmsg, int fd, struct __sanitizer_mmsghdr *msgvec,
31443156 void *ctx;
31453157 COMMON_INTERCEPTOR_ENTER(ctx, recvmmsg, fd, msgvec, vlen, flags, timeout);
31463158 if (timeout) COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout, struct_timespec_sz);
3147 int res = REAL(recvmmsg)(fd, msgvec, vlen, flags, timeout);
3159 int res =
3160 COMMON_INTERCEPTOR_BLOCK_REAL(recvmmsg)(fd, msgvec, vlen, flags, timeout);
31483161 if (res >= 0) {
31493162 if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
31503163 for (int i = 0; i < res; ++i) {
......@@ -3222,7 +3235,7 @@ INTERCEPTOR(SSIZE_T, sendmsg, int fd, struct __sanitizer_msghdr *msg,
32223235 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
32233236 COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
32243237 }
3225 SSIZE_T res = REAL(sendmsg)(fd, msg, flags);
3238 SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(sendmsg)(fd, msg, flags);
32263239 if (common_flags()->intercept_send && res >= 0 && msg)
32273240 read_msghdr(ctx, msg, res);
32283241 return res;
......@@ -3241,7 +3254,7 @@ INTERCEPTOR(int, sendmmsg, int fd, struct __sanitizer_mmsghdr *msgvec,
32413254 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
32423255 COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
32433256 }
3244 int res = REAL(sendmmsg)(fd, msgvec, vlen, flags);
3257 int res = COMMON_INTERCEPTOR_BLOCK_REAL(sendmmsg)(fd, msgvec, vlen, flags);
32453258 if (res >= 0 && msgvec) {
32463259 for (int i = 0; i < res; ++i) {
32473260 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &msgvec[i].msg_len,
......@@ -3264,7 +3277,7 @@ INTERCEPTOR(int, msgsnd, int msqid, const void *msgp, SIZE_T msgsz,
32643277 COMMON_INTERCEPTOR_ENTER(ctx, msgsnd, msqid, msgp, msgsz, msgflg);
32653278 if (msgp)
32663279 COMMON_INTERCEPTOR_READ_RANGE(ctx, msgp, sizeof(long) + msgsz);
3267 int res = REAL(msgsnd)(msqid, msgp, msgsz, msgflg);
3280 int res = COMMON_INTERCEPTOR_BLOCK_REAL(msgsnd)(msqid, msgp, msgsz, msgflg);
32683281 return res;
32693282}
32703283
......@@ -3272,7 +3285,8 @@ INTERCEPTOR(SSIZE_T, msgrcv, int msqid, void *msgp, SIZE_T msgsz,
32723285 long msgtyp, int msgflg) {
32733286 void *ctx;
32743287 COMMON_INTERCEPTOR_ENTER(ctx, msgrcv, msqid, msgp, msgsz, msgtyp, msgflg);
3275 SSIZE_T len = REAL(msgrcv)(msqid, msgp, msgsz, msgtyp, msgflg);
3288 SSIZE_T len =
3289 COMMON_INTERCEPTOR_BLOCK_REAL(msgrcv)(msqid, msgp, msgsz, msgtyp, msgflg);
32763290 if (len != -1)
32773291 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msgp, sizeof(long) + len);
32783292 return len;
......@@ -6116,7 +6130,7 @@ INTERCEPTOR(int, flopen, const char *path, int flags, ...) {
61166130 if (path) {
61176131 COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
61186132 }
6119 return REAL(flopen)(path, flags, mode);
6133 return COMMON_INTERCEPTOR_BLOCK_REAL(flopen)(path, flags, mode);
61206134}
61216135
61226136INTERCEPTOR(int, flopenat, int dirfd, const char *path, int flags, ...) {
......@@ -6129,7 +6143,7 @@ INTERCEPTOR(int, flopenat, int dirfd, const char *path, int flags, ...) {
61296143 if (path) {
61306144 COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
61316145 }
6132 return REAL(flopenat)(dirfd, path, flags, mode);
6146 return COMMON_INTERCEPTOR_BLOCK_REAL(flopenat)(dirfd, path, flags, mode);
61336147}
61346148
61356149#define INIT_FLOPEN \
......@@ -6305,7 +6319,36 @@ INTERCEPTOR(int, fclose, __sanitizer_FILE *fp) {
63056319INTERCEPTOR(void*, dlopen, const char *filename, int flag) {
63066320 void *ctx;
63076321 COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, dlopen, filename, flag);
6308 if (filename) COMMON_INTERCEPTOR_READ_STRING(ctx, filename, 0);
6322
6323 if (filename) {
6324 COMMON_INTERCEPTOR_READ_STRING(ctx, filename, 0);
6325
6326# if !SANITIZER_DYNAMIC
6327 // We care about a very specific use-case: dladdr on
6328 // statically-linked ASan may return <main program>
6329 // instead of the library.
6330 // We therefore only take effect if the sanitizer is statically
6331 // linked, and we don't bother canonicalizing paths because
6332 // dladdr should return the same address both times (we assume
6333 // the user did not canonicalize the result from dladdr).
6334 if (common_flags()->test_only_replace_dlopen_main_program) {
6335 VPrintf(1, "dlopen interceptor: filename: %s\n", filename);
6336
6337 const char *SelfFName = DladdrSelfFName();
6338 VPrintf(1, "dlopen interceptor: DladdrSelfFName: %p %s\n",
6339 (const void *)SelfFName, SelfFName);
6340
6341 if (SelfFName && internal_strcmp(SelfFName, filename) == 0) {
6342 // It's possible they copied the string from dladdr, so
6343 // we do a string comparison rather than pointer comparison.
6344 VPrintf(1, "dlopen interceptor: replacing %s because it matches %s\n",
6345 filename, SelfFName);
6346 filename = (char *)0; // RTLD_DEFAULT
6347 }
6348 }
6349# endif // !SANITIZER_DYNAMIC
6350 }
6351
63096352 void *res = COMMON_INTERCEPTOR_DLOPEN(filename, flag);
63106353 Symbolizer::GetOrInit()->InvalidateModuleList();
63116354 COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, res);
......@@ -6685,7 +6728,7 @@ INTERCEPTOR(SSIZE_T, recv, int fd, void *buf, SIZE_T len, int flags) {
66856728 void *ctx;
66866729 COMMON_INTERCEPTOR_ENTER(ctx, recv, fd, buf, len, flags);
66876730 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
6688 SSIZE_T res = REAL(recv)(fd, buf, len, flags);
6731 SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(recv)(fd, buf, len, flags);
66896732 if (res > 0) {
66906733 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, Min((SIZE_T)res, len));
66916734 }
......@@ -6702,7 +6745,8 @@ INTERCEPTOR(SSIZE_T, recvfrom, int fd, void *buf, SIZE_T len, int flags,
67026745 SIZE_T srcaddr_sz;
67036746 if (srcaddr) srcaddr_sz = *addrlen;
67046747 (void)srcaddr_sz; // prevent "set but not used" warning
6705 SSIZE_T res = REAL(recvfrom)(fd, buf, len, flags, srcaddr, addrlen);
6748 SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(recvfrom)(fd, buf, len, flags,
6749 srcaddr, addrlen);
67066750 if (res > 0)
67076751 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, Min((SIZE_T)res, len));
67086752 if (res >= 0 && srcaddr)
......@@ -6725,7 +6769,7 @@ INTERCEPTOR(SSIZE_T, send, int fd, void *buf, SIZE_T len, int flags) {
67256769 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
67266770 COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
67276771 }
6728 SSIZE_T res = REAL(send)(fd, buf, len, flags);
6772 SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(send)(fd, buf, len, flags);
67296773 if (common_flags()->intercept_send && res > 0)
67306774 COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, Min((SIZE_T)res, len));
67316775 return res;
......@@ -6740,7 +6784,8 @@ INTERCEPTOR(SSIZE_T, sendto, int fd, void *buf, SIZE_T len, int flags,
67406784 COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
67416785 }
67426786 // Can't check dstaddr as it may have uninitialized padding at the end.
6743 SSIZE_T res = REAL(sendto)(fd, buf, len, flags, dstaddr, addrlen);
6787 SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(sendto)(fd, buf, len, flags,
6788 dstaddr, addrlen);
67446789 if (common_flags()->intercept_send && res > 0)
67456790 COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, Min((SIZE_T)res, len));
67466791 return res;
......@@ -6753,25 +6798,25 @@ INTERCEPTOR(SSIZE_T, sendto, int fd, void *buf, SIZE_T len, int flags,
67536798#endif
67546799
67556800#if SANITIZER_INTERCEPT_EVENTFD_READ_WRITE
6756INTERCEPTOR(int, eventfd_read, int fd, u64 *value) {
6801INTERCEPTOR(int, eventfd_read, int fd, __sanitizer_eventfd_t *value) {
67576802 void *ctx;
67586803 COMMON_INTERCEPTOR_ENTER(ctx, eventfd_read, fd, value);
67596804 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
6760 int res = REAL(eventfd_read)(fd, value);
6805 int res = COMMON_INTERCEPTOR_BLOCK_REAL(eventfd_read)(fd, value);
67616806 if (res == 0) {
67626807 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, sizeof(*value));
67636808 if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
67646809 }
67656810 return res;
67666811}
6767INTERCEPTOR(int, eventfd_write, int fd, u64 value) {
6812INTERCEPTOR(int, eventfd_write, int fd, __sanitizer_eventfd_t value) {
67686813 void *ctx;
67696814 COMMON_INTERCEPTOR_ENTER(ctx, eventfd_write, fd, value);
67706815 if (fd >= 0) {
67716816 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
67726817 COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
67736818 }
6774 int res = REAL(eventfd_write)(fd, value);
6819 int res = COMMON_INTERCEPTOR_BLOCK_REAL(eventfd_write)(fd, value);
67756820 return res;
67766821}
67776822#define INIT_EVENTFD_READ_WRITE \
......@@ -7394,7 +7439,8 @@ INTERCEPTOR(int, open_by_handle_at, int mount_fd, struct file_handle* handle,
73947439 COMMON_INTERCEPTOR_READ_RANGE(
73957440 ctx, &sanitizer_handle->f_handle, sanitizer_handle->handle_bytes);
73967441
7397 return REAL(open_by_handle_at)(mount_fd, handle, flags);
7442 return COMMON_INTERCEPTOR_BLOCK_REAL(open_by_handle_at)(mount_fd, handle,
7443 flags);
73987444}
73997445
74007446#define INIT_OPEN_BY_HANDLE_AT COMMON_INTERCEPT_FUNCTION(open_by_handle_at)
......@@ -7609,9 +7655,9 @@ static void write_protoent(void *ctx, struct __sanitizer_protoent *p) {
76097655 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_aliases, pp_size * sizeof(char *));
76107656}
76117657
7612INTERCEPTOR(struct __sanitizer_protoent *, getprotoent) {
7658INTERCEPTOR(struct __sanitizer_protoent *, getprotoent,) {
76137659 void *ctx;
7614 COMMON_INTERCEPTOR_ENTER(ctx, getprotoent);
7660 COMMON_INTERCEPTOR_ENTER(ctx, getprotoent,);
76157661 struct __sanitizer_protoent *p = REAL(getprotoent)();
76167662 if (p)
76177663 write_protoent(ctx, p);
......@@ -7698,9 +7744,9 @@ INTERCEPTOR(int, getprotobynumber_r, int num,
76987744#endif
76997745
77007746#if SANITIZER_INTERCEPT_NETENT
7701INTERCEPTOR(struct __sanitizer_netent *, getnetent) {
7747INTERCEPTOR(struct __sanitizer_netent *, getnetent,) {
77027748 void *ctx;
7703 COMMON_INTERCEPTOR_ENTER(ctx, getnetent);
7749 COMMON_INTERCEPTOR_ENTER(ctx, getnetent,);
77047750 struct __sanitizer_netent *n = REAL(getnetent)();
77057751 if (n) {
77067752 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));
......@@ -9862,9 +9908,9 @@ INTERCEPTOR(char *, fdevname_r, int fd, char *buf, SIZE_T len) {
98629908#endif
98639909
98649910#if SANITIZER_INTERCEPT_GETUSERSHELL
9865INTERCEPTOR(char *, getusershell) {
9911INTERCEPTOR(char *, getusershell,) {
98669912 void *ctx;
9867 COMMON_INTERCEPTOR_ENTER(ctx, getusershell);
9913 COMMON_INTERCEPTOR_ENTER(ctx, getusershell,);
98689914 char *res = REAL(getusershell)();
98699915 if (res)
98709916 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
......@@ -9933,7 +9979,13 @@ INTERCEPTOR(void, sl_free, void *sl, int freeall) {
99339979INTERCEPTOR(SSIZE_T, getrandom, void *buf, SIZE_T buflen, unsigned int flags) {
99349980 void *ctx;
99359981 COMMON_INTERCEPTOR_ENTER(ctx, getrandom, buf, buflen, flags);
9936 SSIZE_T n = REAL(getrandom)(buf, buflen, flags);
9982 // If GRND_NONBLOCK is set in the flags, it is non blocking.
9983 static const int grnd_nonblock = 1;
9984 SSIZE_T n;
9985 if ((flags & grnd_nonblock))
9986 n = REAL(getrandom)(buf, buflen, flags);
9987 else
9988 n = COMMON_INTERCEPTOR_BLOCK_REAL(getrandom)(buf, buflen, flags);
99379989 if (n > 0) {
99389990 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, n);
99399991 }
......@@ -10180,20 +10232,6 @@ INTERCEPTOR(int, __xuname, int size, void *utsname) {
1018010232#define INIT___XUNAME
1018110233#endif
1018210234
10183#if SANITIZER_INTERCEPT_HEXDUMP
10184INTERCEPTOR(void, hexdump, const void *ptr, int length, const char *header, int flags) {
10185 void *ctx;
10186 COMMON_INTERCEPTOR_ENTER(ctx, hexdump, ptr, length, header, flags);
10187 COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, length);
10188 COMMON_INTERCEPTOR_READ_RANGE(ctx, header, internal_strlen(header) + 1);
10189 REAL(hexdump)(ptr, length, header, flags);
10190}
10191
10192#define INIT_HEXDUMP COMMON_INTERCEPT_FUNCTION(hexdump);
10193#else
10194#define INIT_HEXDUMP
10195#endif
10196
1019710235#if SANITIZER_INTERCEPT_ARGP_PARSE
1019810236INTERCEPTOR(int, argp_parse, const struct argp *argp, int argc, char **argv,
1019910237 unsigned flags, int *arg_index, void *input) {
......@@ -10226,6 +10264,38 @@ INTERCEPTOR(int, cpuset_getaffinity, int level, int which, __int64_t id, SIZE_T
1022610264#define INIT_CPUSET_GETAFFINITY
1022710265#endif
1022810266
10267#if SANITIZER_INTERCEPT_PREADV2
10268INTERCEPTOR(SSIZE_T, preadv2, int fd, __sanitizer_iovec *iov, int iovcnt,
10269 OFF_T offset, int flags) {
10270 void *ctx;
10271 COMMON_INTERCEPTOR_ENTER(ctx, preadv2, fd, iov, iovcnt, offset, flags);
10272 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
10273 SSIZE_T res = REAL(preadv2)(fd, iov, iovcnt, offset, flags);
10274 if (res > 0) write_iovec(ctx, iov, iovcnt, res);
10275 if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
10276 return res;
10277}
10278#define INIT_PREADV2 COMMON_INTERCEPT_FUNCTION(preadv2)
10279#else
10280#define INIT_PREADV2
10281#endif
10282
10283#if SANITIZER_INTERCEPT_PWRITEV2
10284INTERCEPTOR(SSIZE_T, pwritev2, int fd, __sanitizer_iovec *iov, int iovcnt,
10285 OFF_T offset, int flags) {
10286 void *ctx;
10287 COMMON_INTERCEPTOR_ENTER(ctx, pwritev2, fd, iov, iovcnt, offset, flags);
10288 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
10289 if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
10290 SSIZE_T res = REAL(pwritev2)(fd, iov, iovcnt, offset, flags);
10291 if (res > 0) read_iovec(ctx, iov, iovcnt, res);
10292 return res;
10293}
10294#define INIT_PWRITEV2 COMMON_INTERCEPT_FUNCTION(pwritev2)
10295#else
10296#define INIT_PWRITEV2
10297#endif
10298
1022910299#include "sanitizer_common_interceptors_netbsd_compat.inc"
1023010300
1023110301namespace __sanitizer {
......@@ -10543,9 +10613,10 @@ static void InitializeCommonInterceptors() {
1054310613 INIT_PROCCTL
1054410614 INIT_UNAME;
1054510615 INIT___XUNAME;
10546 INIT_HEXDUMP;
1054710616 INIT_ARGP_PARSE;
1054810617 INIT_CPUSET_GETAFFINITY;
10618 INIT_PREADV2;
10619 INIT_PWRITEV2;
1054910620
1055010621 INIT___PRINTF_CHK;
1055110622}
lib/tsan/sanitizer_common/sanitizer_common_interceptors_format.inc+8-7
......@@ -547,24 +547,25 @@ static void printf_common(void *ctx, const char *format, va_list aq) {
547547 continue;
548548 } else if (size == FSS_STRLEN) {
549549 if (void *argp = va_arg(aq, void *)) {
550 uptr len;
550551 if (dir.starredPrecision) {
551552 // FIXME: properly support starred precision for strings.
552 size = 0;
553 len = 0;
553554 } else if (dir.fieldPrecision > 0) {
554555 // Won't read more than "precision" symbols.
555 size = internal_strnlen((const char *)argp, dir.fieldPrecision);
556 if (size < dir.fieldPrecision) size++;
556 len = internal_strnlen((const char *)argp, dir.fieldPrecision);
557 if (len < (uptr)dir.fieldPrecision)
558 len++;
557559 } else {
558560 // Whole string will be accessed.
559 size = internal_strlen((const char *)argp) + 1;
561 len = internal_strlen((const char *)argp) + 1;
560562 }
561 COMMON_INTERCEPTOR_READ_RANGE(ctx, argp, size);
563 COMMON_INTERCEPTOR_READ_RANGE(ctx, argp, len);
562564 }
563565 } else if (size == FSS_WCSLEN) {
564566 if (void *argp = va_arg(aq, void *)) {
565567 // FIXME: Properly support wide-character strings (via wcsrtombs).
566 size = 0;
567 COMMON_INTERCEPTOR_READ_RANGE(ctx, argp, size);
568 COMMON_INTERCEPTOR_READ_RANGE(ctx, argp, 0);
568569 }
569570 } else {
570571 // Skip non-pointer args
lib/tsan/sanitizer_common/sanitizer_common_interface.inc+1
......@@ -46,6 +46,7 @@ INTERFACE_FUNCTION(__sanitizer_purge_allocator)
4646INTERFACE_FUNCTION(__sanitizer_print_memory_profile)
4747INTERFACE_WEAK_FUNCTION(__sanitizer_free_hook)
4848INTERFACE_WEAK_FUNCTION(__sanitizer_malloc_hook)
49INTERFACE_WEAK_FUNCTION(__sanitizer_ignore_free_hook)
4950// Memintrinsic functions.
5051INTERFACE_FUNCTION(__sanitizer_internal_memcpy)
5152INTERFACE_FUNCTION(__sanitizer_internal_memmove)
lib/tsan/sanitizer_common/sanitizer_common_interface_posix.inc+1
......@@ -9,6 +9,7 @@
99//===----------------------------------------------------------------------===//
1010INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_code)
1111INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_data)
12INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_frame)
1213INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_demangle)
1314INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_flush)
1415INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_set_demangle)
lib/tsan/sanitizer_common/sanitizer_common_libcdep.cpp+6-4
......@@ -87,8 +87,8 @@ void MaybeStartBackgroudThread() {
8787 if (!common_flags()->hard_rss_limit_mb &&
8888 !common_flags()->soft_rss_limit_mb &&
8989 !common_flags()->heap_profile) return;
90 if (!&real_pthread_create) {
91 VPrintf(1, "%s: real_pthread_create undefined\n", SanitizerToolName);
90 if (!&internal_pthread_create) {
91 VPrintf(1, "%s: internal_pthread_create undefined\n", SanitizerToolName);
9292 return; // Can't spawn the thread anyway.
9393 }
9494
......@@ -119,8 +119,10 @@ void MaybeStartBackgroudThread() {}
119119#endif
120120
121121void WriteToSyslog(const char *msg) {
122 if (!msg)
123 return;
122124 InternalScopedString msg_copy;
123 msg_copy.append("%s", msg);
125 msg_copy.Append(msg);
124126 const char *p = msg_copy.data();
125127
126128 // Print one line at a time.
......@@ -167,7 +169,7 @@ void ReserveShadowMemoryRange(uptr beg, uptr end, const char *name,
167169 : !MmapFixedNoReserve(beg, size, name)) {
168170 Report(
169171 "ReserveShadowMemoryRange failed while trying to map 0x%zx bytes. "
170 "Perhaps you're using ulimit -v\n",
172 "Perhaps you're using ulimit -v or ulimit -d\n",
171173 size);
172174 Abort();
173175 }
lib/tsan/sanitizer_common/sanitizer_common_syscalls.inc+35
......@@ -38,6 +38,10 @@
3838// Called before fork syscall.
3939// COMMON_SYSCALL_POST_FORK(long res)
4040// Called after fork syscall.
41// COMMON_SYSCALL_BLOCKING_START()
42// Called before blocking syscall.
43// COMMON_SYSCALL_BLOCKING_END()
44// Called after blocking syscall.
4145//===----------------------------------------------------------------------===//
4246
4347#include "sanitizer_platform.h"
......@@ -85,6 +89,16 @@
8589 {}
8690# endif
8791
92# ifndef COMMON_SYSCALL_BLOCKING_START
93# define COMMON_SYSCALL_BLOCKING_START() \
94 {}
95# endif
96
97# ifndef COMMON_SYSCALL_BLOCKING_END
98# define COMMON_SYSCALL_BLOCKING_END() \
99 {}
100# endif
101
88102// FIXME: do some kind of PRE_READ for all syscall arguments (int(s) and such).
89103
90104extern "C" {
......@@ -2808,6 +2822,15 @@ PRE_SYSCALL(fchownat)
28082822POST_SYSCALL(fchownat)
28092823(long res, long dfd, const void *filename, long user, long group, long flag) {}
28102824
2825PRE_SYSCALL(fchmodat2)(long dfd, const void *filename, long mode, long flag) {
2826 if (filename)
2827 PRE_READ(filename,
2828 __sanitizer::internal_strlen((const char *)filename) + 1);
2829}
2830
2831POST_SYSCALL(fchmodat2)
2832(long res, long dfd, const void *filename, long mode, long flag) {}
2833
28112834PRE_SYSCALL(openat)(long dfd, const void *filename, long flags, long mode) {
28122835 if (filename)
28132836 PRE_READ(filename,
......@@ -3167,6 +3190,18 @@ POST_SYSCALL(sigaltstack)(long res, void *ss, void *oss) {
31673190 }
31683191 }
31693192}
3193
3194PRE_SYSCALL(futex)
3195(void *uaddr, long futex_op, long val, void *timeout, void *uaddr2, long val3) {
3196 COMMON_SYSCALL_BLOCKING_START();
3197}
3198
3199POST_SYSCALL(futex)
3200(long res, void *uaddr, long futex_op, long val, void *timeout, void *uaddr2,
3201 long val3) {
3202 COMMON_SYSCALL_BLOCKING_END();
3203}
3204
31703205} // extern "C"
31713206
31723207# undef PRE_SYSCALL
lib/tsan/sanitizer_common/sanitizer_dl.cpp created+37
......@@ -0,0 +1,37 @@
1//===-- sanitizer_dl.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 has helper functions that depend on libc's dynamic loading
10// introspection.
11//
12//===----------------------------------------------------------------------===//
13
14#include "sanitizer_dl.h"
15
16#include "sanitizer_common/sanitizer_platform.h"
17
18#if SANITIZER_GLIBC
19# include <dlfcn.h>
20#endif
21
22namespace __sanitizer {
23extern const char *SanitizerToolName;
24
25const char *DladdrSelfFName(void) {
26#if SANITIZER_GLIBC
27 Dl_info info;
28 int ret = dladdr((void *)&SanitizerToolName, &info);
29 if (ret) {
30 return info.dli_fname;
31 }
32#endif
33
34 return nullptr;
35}
36
37} // namespace __sanitizer
lib/tsan/sanitizer_common/sanitizer_dl.h created+26
......@@ -0,0 +1,26 @@
1//===-- sanitizer_dl.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 has helper functions that depend on libc's dynamic loading
10// introspection.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef SANITIZER_DL_H
15#define SANITIZER_DL_H
16
17namespace __sanitizer {
18
19// Returns the path to the shared object or - in the case of statically linked
20// sanitizers
21// - the main program itself, that contains the sanitizer.
22const char* DladdrSelfFName(void);
23
24} // namespace __sanitizer
25
26#endif // SANITIZER_DL_H
lib/tsan/sanitizer_common/sanitizer_file.cpp+3-1
......@@ -69,7 +69,7 @@ void ReportFile::ReopenIfNecessary() {
6969 WriteToFile(kStderrFd, ErrorMsgPrefix, internal_strlen(ErrorMsgPrefix));
7070 WriteToFile(kStderrFd, full_path, internal_strlen(full_path));
7171 char errmsg[100];
72 internal_snprintf(errmsg, sizeof(errmsg), " (reason: %d)", err);
72 internal_snprintf(errmsg, sizeof(errmsg), " (reason: %d)\n", err);
7373 WriteToFile(kStderrFd, errmsg, internal_strlen(errmsg));
7474 Die();
7575 }
......@@ -88,6 +88,8 @@ static void RecursiveCreateParentDirs(char *path) {
8888 const char *ErrorMsgPrefix = "ERROR: Can't create directory: ";
8989 WriteToFile(kStderrFd, ErrorMsgPrefix, internal_strlen(ErrorMsgPrefix));
9090 WriteToFile(kStderrFd, path, internal_strlen(path));
91 const char *ErrorMsgSuffix = "\n";
92 WriteToFile(kStderrFd, ErrorMsgSuffix, internal_strlen(ErrorMsgSuffix));
9193 Die();
9294 }
9395 path[i] = save;
lib/tsan/sanitizer_common/sanitizer_file.h+1-1
......@@ -84,7 +84,7 @@ bool IsPathSeparator(const char c);
8484bool IsAbsolutePath(const char *path);
8585// Returns true on success, false on failure.
8686bool CreateDir(const char *pathname);
87// Starts a subprocess and returs its pid.
87// Starts a subprocess and returns its pid.
8888// If *_fd parameters are not kInvalidFd their corresponding input/output
8989// streams will be redirect to the file. The files will always be closed
9090// in parent process even in case of an error.
lib/tsan/sanitizer_common/sanitizer_flag_parser.cpp+3-4
......@@ -19,8 +19,6 @@
1919
2020namespace __sanitizer {
2121
22LowLevelAllocator FlagParser::Alloc;
23
2422class UnknownFlags {
2523 static const int kMaxUnknownFlags = 20;
2624 const char *unknown_flags_[kMaxUnknownFlags];
......@@ -49,7 +47,7 @@ void ReportUnrecognizedFlags() {
4947
5048char *FlagParser::ll_strndup(const char *s, uptr n) {
5149 uptr len = internal_strnlen(s, n);
52 char *s2 = (char*)Alloc.Allocate(len + 1);
50 char *s2 = (char *)GetGlobalLowLevelAllocator().Allocate(len + 1);
5351 internal_memcpy(s2, s, len);
5452 s2[len] = 0;
5553 return s2;
......@@ -185,7 +183,8 @@ void FlagParser::RegisterHandler(const char *name, FlagHandlerBase *handler,
185183}
186184
187185FlagParser::FlagParser() : n_flags_(0), buf_(nullptr), pos_(0) {
188 flags_ = (Flag *)Alloc.Allocate(sizeof(Flag) * kMaxFlags);
186 flags_ =
187 (Flag *)GetGlobalLowLevelAllocator().Allocate(sizeof(Flag) * kMaxFlags);
189188}
190189
191190} // namespace __sanitizer
lib/tsan/sanitizer_common/sanitizer_flag_parser.h+1-3
......@@ -178,8 +178,6 @@ class FlagParser {
178178 bool ParseFile(const char *path, bool ignore_missing);
179179 void PrintFlagDescriptions();
180180
181 static LowLevelAllocator Alloc;
182
183181 private:
184182 void fatal_error(const char *err);
185183 bool is_space(char c);
......@@ -193,7 +191,7 @@ class FlagParser {
193191template <typename T>
194192static void RegisterFlag(FlagParser *parser, const char *name, const char *desc,
195193 T *var) {
196 FlagHandler<T> *fh = new (FlagParser::Alloc) FlagHandler<T>(var);
194 FlagHandler<T> *fh = new (GetGlobalLowLevelAllocator()) FlagHandler<T>(var);
197195 parser->RegisterHandler(name, fh, desc);
198196}
199197
lib/tsan/sanitizer_common/sanitizer_flags.cpp+2-2
......@@ -108,11 +108,11 @@ class FlagHandlerInclude final : public FlagHandlerBase {
108108};
109109
110110void RegisterIncludeFlags(FlagParser *parser, CommonFlags *cf) {
111 FlagHandlerInclude *fh_include = new (FlagParser::Alloc)
111 FlagHandlerInclude *fh_include = new (GetGlobalLowLevelAllocator())
112112 FlagHandlerInclude(parser, /*ignore_missing*/ false);
113113 parser->RegisterHandler("include", fh_include,
114114 "read more options from the given file");
115 FlagHandlerInclude *fh_include_if_exists = new (FlagParser::Alloc)
115 FlagHandlerInclude *fh_include_if_exists = new (GetGlobalLowLevelAllocator())
116116 FlagHandlerInclude(parser, /*ignore_missing*/ true);
117117 parser->RegisterHandler(
118118 "include_if_exists", fh_include_if_exists,
lib/tsan/sanitizer_common/sanitizer_flags.inc+13
......@@ -269,3 +269,16 @@ COMMON_FLAG(bool, detect_write_exec, false,
269269COMMON_FLAG(bool, test_only_emulate_no_memorymap, false,
270270 "TEST ONLY fail to read memory mappings to emulate sanitized "
271271 "\"init\"")
272// With static linking, dladdr((void*)pthread_join) or similar will return the
273// path to the main program. This flag will replace dlopen(<main program,...>
274// with dlopen(NULL,...), which is the correct way to get a handle to the main
275// program.
276COMMON_FLAG(bool, test_only_replace_dlopen_main_program, false,
277 "TEST ONLY replace dlopen(<main program>,...) with dlopen(NULL)")
278
279COMMON_FLAG(bool, enable_symbolizer_markup, SANITIZER_FUCHSIA,
280 "Use sanitizer symbolizer markup, available on Linux "
281 "and always set true for Fuchsia.")
282
283COMMON_FLAG(bool, detect_invalid_join, true,
284 "If set, check invalid joins of threads.")
lib/tsan/sanitizer_common/sanitizer_flat_map.h+4
......@@ -109,6 +109,10 @@ class TwoLevelMap {
109109 return *AddressSpaceView::LoadWritable(&map2[idx % kSize2]);
110110 }
111111
112 void Lock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS { mu_.Lock(); }
113
114 void Unlock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS { mu_.Unlock(); }
115
112116 private:
113117 constexpr uptr MmapSize() const {
114118 return RoundUpTo(kSize2 * sizeof(T), GetPageSizeCached());
lib/tsan/sanitizer_common/sanitizer_freebsd.h deleted-137
......@@ -1,137 +0,0 @@
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+82-25
......@@ -129,6 +129,60 @@ uptr GetMaxVirtualAddress() { return GetMaxUserVirtualAddress(); }
129129
130130bool ErrorIsOOM(error_t err) { return err == ZX_ERR_NO_MEMORY; }
131131
132// For any sanitizer internal that needs to map something which can be unmapped
133// later, first attempt to map to a pre-allocated VMAR. This helps reduce
134// fragmentation from many small anonymous mmap calls. A good value for this
135// VMAR size would be the total size of your typical sanitizer internal objects
136// allocated in an "average" process lifetime. Examples of this include:
137// FakeStack, LowLevelAllocator mappings, TwoLevelMap, InternalMmapVector,
138// StackStore, CreateAsanThread, etc.
139//
140// This is roughly equal to the total sum of sanitizer internal mappings for a
141// large test case.
142constexpr size_t kSanitizerHeapVmarSize = 13ULL << 20;
143static zx_handle_t gSanitizerHeapVmar = ZX_HANDLE_INVALID;
144
145static zx_status_t GetSanitizerHeapVmar(zx_handle_t *vmar) {
146 zx_status_t status = ZX_OK;
147 if (gSanitizerHeapVmar == ZX_HANDLE_INVALID) {
148 CHECK_EQ(kSanitizerHeapVmarSize % GetPageSizeCached(), 0);
149 uintptr_t base;
150 status = _zx_vmar_allocate(
151 _zx_vmar_root_self(),
152 ZX_VM_CAN_MAP_READ | ZX_VM_CAN_MAP_WRITE | ZX_VM_CAN_MAP_SPECIFIC, 0,
153 kSanitizerHeapVmarSize, &gSanitizerHeapVmar, &base);
154 }
155 *vmar = gSanitizerHeapVmar;
156 if (status == ZX_OK)
157 CHECK_NE(gSanitizerHeapVmar, ZX_HANDLE_INVALID);
158 return status;
159}
160
161static zx_status_t TryVmoMapSanitizerVmar(zx_vm_option_t options,
162 size_t vmar_offset, zx_handle_t vmo,
163 size_t size, uintptr_t *addr,
164 zx_handle_t *vmar_used = nullptr) {
165 zx_handle_t vmar;
166 zx_status_t status = GetSanitizerHeapVmar(&vmar);
167 if (status != ZX_OK)
168 return status;
169
170 status = _zx_vmar_map(gSanitizerHeapVmar, options, vmar_offset, vmo,
171 /*vmo_offset=*/0, size, addr);
172 if (vmar_used)
173 *vmar_used = gSanitizerHeapVmar;
174 if (status == ZX_ERR_NO_RESOURCES || status == ZX_ERR_INVALID_ARGS) {
175 // This means there's no space in the heap VMAR, so fallback to the root
176 // VMAR.
177 status = _zx_vmar_map(_zx_vmar_root_self(), options, vmar_offset, vmo,
178 /*vmo_offset=*/0, size, addr);
179 if (vmar_used)
180 *vmar_used = _zx_vmar_root_self();
181 }
182
183 return status;
184}
185
132186static void *DoAnonymousMmapOrDie(uptr size, const char *mem_type,
133187 bool raw_report, bool die_for_nomem) {
134188 size = RoundUpTo(size, GetPageSize());
......@@ -144,11 +198,9 @@ static void *DoAnonymousMmapOrDie(uptr size, const char *mem_type,
144198 _zx_object_set_property(vmo, ZX_PROP_NAME, mem_type,
145199 internal_strlen(mem_type));
146200
147 // TODO(mcgrathr): Maybe allocate a VMAR for all sanitizer heap and use that?
148201 uintptr_t addr;
149 status =
150 _zx_vmar_map(_zx_vmar_root_self(), ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, 0,
151 vmo, 0, size, &addr);
202 status = TryVmoMapSanitizerVmar(ZX_VM_PERM_READ | ZX_VM_PERM_WRITE,
203 /*vmar_offset=*/0, vmo, size, &addr);
152204 _zx_handle_close(vmo);
153205
154206 if (status != ZX_OK) {
......@@ -226,27 +278,32 @@ static uptr DoMmapFixedOrDie(zx_handle_t vmar, uptr fixed_addr, uptr map_size,
226278
227279uptr ReservedAddressRange::Map(uptr fixed_addr, uptr map_size,
228280 const char *name) {
229 return DoMmapFixedOrDie(os_handle_, fixed_addr, map_size, base_, name_,
230 false);
281 return DoMmapFixedOrDie(os_handle_, fixed_addr, map_size, base_,
282 name ? name : name_, false);
231283}
232284
233285uptr ReservedAddressRange::MapOrDie(uptr fixed_addr, uptr map_size,
234286 const char *name) {
235 return DoMmapFixedOrDie(os_handle_, fixed_addr, map_size, base_, name_, true);
287 return DoMmapFixedOrDie(os_handle_, fixed_addr, map_size, base_,
288 name ? name : name_, true);
236289}
237290
238void UnmapOrDieVmar(void *addr, uptr size, zx_handle_t target_vmar) {
291void UnmapOrDieVmar(void *addr, uptr size, zx_handle_t target_vmar,
292 bool raw_report) {
239293 if (!addr || !size)
240294 return;
241295 size = RoundUpTo(size, GetPageSize());
242296
243297 zx_status_t status =
244298 _zx_vmar_unmap(target_vmar, reinterpret_cast<uintptr_t>(addr), size);
245 if (status != ZX_OK) {
246 Report("ERROR: %s failed to deallocate 0x%zx (%zd) bytes at address %p\n",
247 SanitizerToolName, size, size, addr);
248 CHECK("unable to unmap" && 0);
299 if (status == ZX_ERR_INVALID_ARGS && target_vmar == gSanitizerHeapVmar) {
300 // If there wasn't any space in the heap vmar, the fallback was the root
301 // vmar.
302 status = _zx_vmar_unmap(_zx_vmar_root_self(),
303 reinterpret_cast<uintptr_t>(addr), size);
249304 }
305 if (status != ZX_OK)
306 ReportMunmapFailureAndDie(addr, size, status, raw_report);
250307
251308 DecreaseTotalMmap(size);
252309}
......@@ -268,7 +325,8 @@ void ReservedAddressRange::Unmap(uptr addr, uptr size) {
268325 }
269326 // Partial unmapping does not affect the fact that the initial range is still
270327 // reserved, and the resulting unmapped memory can't be reused.
271 UnmapOrDieVmar(reinterpret_cast<void *>(addr), size, vmar);
328 UnmapOrDieVmar(reinterpret_cast<void *>(addr), size, vmar,
329 /*raw_report=*/false);
272330}
273331
274332// This should never be called.
......@@ -307,17 +365,16 @@ void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment,
307365 _zx_object_set_property(vmo, ZX_PROP_NAME, mem_type,
308366 internal_strlen(mem_type));
309367
310 // TODO(mcgrathr): Maybe allocate a VMAR for all sanitizer heap and use that?
311
312368 // Map a larger size to get a chunk of address space big enough that
313369 // it surely contains an aligned region of the requested size. Then
314370 // overwrite the aligned middle portion with a mapping from the
315371 // beginning of the VMO, and unmap the excess before and after.
316372 size_t map_size = size + alignment;
317373 uintptr_t addr;
318 status =
319 _zx_vmar_map(_zx_vmar_root_self(), ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, 0,
320 vmo, 0, map_size, &addr);
374 zx_handle_t vmar_used;
375 status = TryVmoMapSanitizerVmar(ZX_VM_PERM_READ | ZX_VM_PERM_WRITE,
376 /*vmar_offset=*/0, vmo, map_size, &addr,
377 &vmar_used);
321378 if (status == ZX_OK) {
322379 uintptr_t map_addr = addr;
323380 uintptr_t map_end = map_addr + map_size;
......@@ -325,12 +382,12 @@ void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment,
325382 uintptr_t end = addr + size;
326383 if (addr != map_addr) {
327384 zx_info_vmar_t info;
328 status = _zx_object_get_info(_zx_vmar_root_self(), ZX_INFO_VMAR, &info,
329 sizeof(info), NULL, NULL);
385 status = _zx_object_get_info(vmar_used, ZX_INFO_VMAR, &info, sizeof(info),
386 NULL, NULL);
330387 if (status == ZX_OK) {
331388 uintptr_t new_addr;
332389 status = _zx_vmar_map(
333 _zx_vmar_root_self(),
390 vmar_used,
334391 ZX_VM_PERM_READ | ZX_VM_PERM_WRITE | ZX_VM_SPECIFIC_OVERWRITE,
335392 addr - info.base, vmo, 0, size, &new_addr);
336393 if (status == ZX_OK)
......@@ -338,9 +395,9 @@ void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment,
338395 }
339396 }
340397 if (status == ZX_OK && addr != map_addr)
341 status = _zx_vmar_unmap(_zx_vmar_root_self(), map_addr, addr - map_addr);
398 status = _zx_vmar_unmap(vmar_used, map_addr, addr - map_addr);
342399 if (status == ZX_OK && end != map_end)
343 status = _zx_vmar_unmap(_zx_vmar_root_self(), end, map_end - end);
400 status = _zx_vmar_unmap(vmar_used, end, map_end - end);
344401 }
345402 _zx_handle_close(vmo);
346403
......@@ -355,8 +412,8 @@ void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment,
355412 return reinterpret_cast<void *>(addr);
356413}
357414
358void UnmapOrDie(void *addr, uptr size) {
359 UnmapOrDieVmar(addr, size, _zx_vmar_root_self());
415void UnmapOrDie(void *addr, uptr size, bool raw_report) {
416 UnmapOrDieVmar(addr, size, gSanitizerHeapVmar, raw_report);
360417}
361418
362419void ReleaseMemoryPagesToOS(uptr beg, uptr end) {
lib/tsan/sanitizer_common/sanitizer_hash.h+1-1
......@@ -62,6 +62,6 @@ class MurMur2Hash64Builder {
6262 return x;
6363 }
6464};
65} //namespace __sanitizer
65} // namespace __sanitizer
6666
6767#endif // SANITIZER_HASH_H
lib/tsan/sanitizer_common/sanitizer_internal_defs.h+25-9
......@@ -15,6 +15,11 @@
1515#include "sanitizer_platform.h"
1616#include "sanitizer_redefine_builtins.h"
1717
18// GCC does not understand __has_feature.
19#if !defined(__has_feature)
20#define __has_feature(x) 0
21#endif
22
1823#ifndef SANITIZER_DEBUG
1924# define SANITIZER_DEBUG 0
2025#endif
......@@ -30,13 +35,20 @@
3035# define SANITIZER_INTERFACE_ATTRIBUTE __declspec(dllexport)
3136#endif
3237# define SANITIZER_WEAK_ATTRIBUTE
38# define SANITIZER_WEAK_IMPORT
3339#elif SANITIZER_GO
3440# define SANITIZER_INTERFACE_ATTRIBUTE
3541# define SANITIZER_WEAK_ATTRIBUTE
42# define SANITIZER_WEAK_IMPORT
3643#else
3744# define SANITIZER_INTERFACE_ATTRIBUTE __attribute__((visibility("default")))
3845# define SANITIZER_WEAK_ATTRIBUTE __attribute__((weak))
39#endif
46# if SANITIZER_APPLE
47# define SANITIZER_WEAK_IMPORT extern "C" __attribute((weak_import))
48# else
49# define SANITIZER_WEAK_IMPORT extern "C" SANITIZER_WEAK_ATTRIBUTE
50# endif // SANITIZER_APPLE
51#endif // SANITIZER_WINDOWS
4052
4153//--------------------------- WEAK FUNCTIONS ---------------------------------//
4254// When working with weak functions, to simplify the code and make it more
......@@ -179,15 +191,19 @@ typedef uptr OFF_T;
179191#endif
180192typedef u64 OFF64_T;
181193
182#if (SANITIZER_WORDSIZE == 64) || SANITIZER_APPLE
183typedef uptr operator_new_size_type;
194#ifdef __SIZE_TYPE__
195typedef __SIZE_TYPE__ usize;
184196#else
185# if 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
197// Since we use this for operator new, usize must match the real size_t, but on
198// 32-bit Windows the definition of uptr does not actually match uintptr_t or
199// size_t because we are working around typedef mismatches for the (S)SIZE_T
200// types used in interception.h.
201// Until the definition of uptr has been fixed we have to special case Win32.
202# if SANITIZER_WINDOWS && SANITIZER_WORDSIZE == 32
203typedef unsigned int usize;
204# else
205typedef uptr usize;
206# endif
191207#endif
192208
193209typedef u64 tid_t;
lib/tsan/sanitizer_common/sanitizer_libc.cpp+16
......@@ -199,6 +199,14 @@ char *internal_strncat(char *dst, const char *src, uptr n) {
199199 return dst;
200200}
201201
202wchar_t *internal_wcscpy(wchar_t *dst, const wchar_t *src) {
203 wchar_t *dst_it = dst;
204 do {
205 *dst_it++ = *src++;
206 } while (*src);
207 return dst;
208}
209
202210uptr internal_strlcpy(char *dst, const char *src, uptr maxlen) {
203211 const uptr srclen = internal_strlen(src);
204212 if (srclen < maxlen) {
......@@ -218,6 +226,14 @@ char *internal_strncpy(char *dst, const char *src, uptr n) {
218226 return dst;
219227}
220228
229wchar_t *internal_wcsncpy(wchar_t *dst, const wchar_t *src, uptr n) {
230 uptr i;
231 for (i = 0; i < n && src[i]; ++i)
232 dst[i] = src[i];
233 internal_memset(dst + i, 0, (n - i) * sizeof(wchar_t));
234 return dst;
235}
236
221237uptr internal_strnlen(const char *s, uptr maxlen) {
222238 uptr i = 0;
223239 while (i < maxlen && s[i]) i++;
lib/tsan/sanitizer_common/sanitizer_libc.h+2-1
......@@ -71,7 +71,8 @@ int internal_snprintf(char *buffer, uptr length, const char *format, ...)
7171 FORMAT(3, 4);
7272uptr internal_wcslen(const wchar_t *s);
7373uptr internal_wcsnlen(const wchar_t *s, uptr maxlen);
74
74wchar_t *internal_wcscpy(wchar_t *dst, const wchar_t *src);
75wchar_t *internal_wcsncpy(wchar_t *dst, const wchar_t *src, uptr maxlen);
7576// Return true if all bytes in [mem, mem+size) are zero.
7677// Optimized for the case when the result is true.
7778bool mem_is_zero(const char *mem, uptr size);
lib/tsan/sanitizer_common/sanitizer_libignore.cpp+2-2
......@@ -105,8 +105,8 @@ void LibIgnore::OnLibraryLoaded(const char *name) {
105105 continue;
106106 if (IsPcInstrumented(range.beg) && IsPcInstrumented(range.end - 1))
107107 continue;
108 VReport(1, "Adding instrumented range 0x%zx-0x%zx from library '%s'\n",
109 range.beg, range.end, mod.full_name());
108 VReport(1, "Adding instrumented range %p-%p from library '%s'\n",
109 (void *)range.beg, (void *)range.end, mod.full_name());
110110 const uptr idx =
111111 atomic_load(&instrumented_ranges_count_, memory_order_relaxed);
112112 CHECK_LT(idx, ARRAY_SIZE(instrumented_code_ranges_));
lib/tsan/sanitizer_common/sanitizer_linux.cpp+1009-833
......@@ -16,101 +16,105 @@
1616#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
1717 SANITIZER_SOLARIS
1818
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
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
3232
3333// For mips64, syscall(__NR_stat) fills the buffer in the 'struct kernel_stat'
3434// format. Struct kernel_stat is defined as 'struct stat' in asm/stat.h. To
3535// access stat from asm/stat.h, without conflicting with definition in
36// sys/stat.h, we use this trick.
37#if SANITIZER_MIPS64
38#include <asm/unistd.h>
39#include <sys/types.h>
40#define stat kernel_stat
41#if SANITIZER_GO
42#undef st_atime
43#undef st_mtime
44#undef st_ctime
45#define st_atime st_atim
46#define st_mtime st_mtim
47#define st_ctime st_ctim
48#endif
49#include <asm/stat.h>
50#undef stat
51#endif
36// sys/stat.h, we use this trick. sparc64 is similar, using
37// syscall(__NR_stat64) and struct kernel_stat64.
38# if SANITIZER_LINUX && (SANITIZER_MIPS64 || SANITIZER_SPARC64)
39# include <asm/unistd.h>
40# include <sys/types.h>
41# define stat kernel_stat
42# if SANITIZER_SPARC64
43# define stat64 kernel_stat64
44# endif
45# if SANITIZER_GO
46# undef st_atime
47# undef st_mtime
48# undef st_ctime
49# define st_atime st_atim
50# define st_mtime st_mtim
51# define st_ctime st_ctim
52# endif
53# include <asm/stat.h>
54# undef stat
55# undef stat64
56# endif
5257
53#include <dlfcn.h>
54#include <errno.h>
55#include <fcntl.h>
56#include <link.h>
57#include <pthread.h>
58#include <sched.h>
59#include <signal.h>
60#include <sys/mman.h>
61#include <sys/param.h>
62#if !SANITIZER_SOLARIS
63#include <sys/ptrace.h>
64#endif
65#include <sys/resource.h>
66#include <sys/stat.h>
67#include <sys/syscall.h>
68#include <sys/time.h>
69#include <sys/types.h>
70#include <ucontext.h>
71#include <unistd.h>
72
73#if SANITIZER_LINUX
74#include <sys/utsname.h>
75#endif
58# include <dlfcn.h>
59# include <errno.h>
60# include <fcntl.h>
61# include <link.h>
62# include <pthread.h>
63# include <sched.h>
64# include <signal.h>
65# include <sys/mman.h>
66# if !SANITIZER_SOLARIS
67# include <sys/ptrace.h>
68# endif
69# include <sys/resource.h>
70# include <sys/stat.h>
71# include <sys/syscall.h>
72# include <sys/time.h>
73# include <sys/types.h>
74# include <ucontext.h>
75# include <unistd.h>
7676
77#if SANITIZER_LINUX && !SANITIZER_ANDROID
78#include <sys/personality.h>
79#endif
77# if SANITIZER_LINUX
78# include <sys/utsname.h>
79# endif
8080
81#if SANITIZER_LINUX && defined(__loongarch__)
82# include <sys/sysmacros.h>
83#endif
81# if SANITIZER_LINUX && !SANITIZER_ANDROID
82# include <sys/personality.h>
83# endif
8484
85#if SANITIZER_FREEBSD
86#include <sys/exec.h>
87#include <sys/procctl.h>
88#include <sys/sysctl.h>
89#include <machine/atomic.h>
85# if SANITIZER_LINUX && defined(__loongarch__)
86# include <sys/sysmacros.h>
87# endif
88
89# if SANITIZER_FREEBSD
90# include <machine/atomic.h>
91# include <sys/exec.h>
92# include <sys/procctl.h>
93# include <sys/sysctl.h>
9094extern "C" {
9195// <sys/umtx.h> must be included after <errno.h> and <sys/types.h> on
9296// FreeBSD 9.2 and 10.0.
93#include <sys/umtx.h>
97# include <sys/umtx.h>
9498}
95#include <sys/thr.h>
96#endif // SANITIZER_FREEBSD
99# include <sys/thr.h>
100# endif // SANITIZER_FREEBSD
97101
98#if SANITIZER_NETBSD
99#include <limits.h> // For NAME_MAX
100#include <sys/sysctl.h>
101#include <sys/exec.h>
102# if SANITIZER_NETBSD
103# include <limits.h> // For NAME_MAX
104# include <sys/exec.h>
105# include <sys/sysctl.h>
102106extern struct ps_strings *__ps_strings;
103#endif // SANITIZER_NETBSD
107# endif // SANITIZER_NETBSD
104108
105#if SANITIZER_SOLARIS
106#include <stdlib.h>
107#include <thread.h>
108#define environ _environ
109#endif
109# if SANITIZER_SOLARIS
110# include <stdlib.h>
111# include <thread.h>
112# define environ _environ
113# endif
110114
111115extern char **environ;
112116
113#if SANITIZER_LINUX
117# if SANITIZER_LINUX
114118// <linux/time.h>
115119struct kernel_timeval {
116120 long tv_sec;
......@@ -123,36 +127,32 @@ const int FUTEX_WAKE = 1;
123127const int FUTEX_PRIVATE_FLAG = 128;
124128const int FUTEX_WAIT_PRIVATE = FUTEX_WAIT | FUTEX_PRIVATE_FLAG;
125129const int FUTEX_WAKE_PRIVATE = FUTEX_WAKE | FUTEX_PRIVATE_FLAG;
126#endif // SANITIZER_LINUX
130# endif // SANITIZER_LINUX
127131
128132// Are we using 32-bit or 64-bit Linux syscalls?
129133// x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32
130134// but it still needs to use 64-bit syscalls.
131#if SANITIZER_LINUX && (defined(__x86_64__) || defined(__powerpc64__) || \
132 SANITIZER_WORDSIZE == 64 || \
133 (defined(__mips__) && _MIPS_SIM == _ABIN32))
134# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1
135#else
136# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0
137#endif
135# if SANITIZER_LINUX && (defined(__x86_64__) || defined(__powerpc64__) || \
136 SANITIZER_WORDSIZE == 64 || \
137 (defined(__mips__) && _MIPS_SIM == _ABIN32))
138# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1
139# else
140# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0
141# endif
138142
139// Note : FreeBSD had implemented both
140// Linux apis, available from
141// future 12.x version most likely
142#if SANITIZER_LINUX && defined(__NR_getrandom)
143# if !defined(GRND_NONBLOCK)
144# define GRND_NONBLOCK 1
145# endif
146# define SANITIZER_USE_GETRANDOM 1
147#else
148# define SANITIZER_USE_GETRANDOM 0
149#endif // SANITIZER_LINUX && defined(__NR_getrandom)
150
151#if SANITIZER_FREEBSD && __FreeBSD_version >= 1200000
152# define SANITIZER_USE_GETENTROPY 1
153#else
154# define SANITIZER_USE_GETENTROPY 0
155#endif
143// Note : FreeBSD implemented both Linux and OpenBSD apis.
144# if SANITIZER_LINUX && defined(__NR_getrandom)
145# if !defined(GRND_NONBLOCK)
146# define GRND_NONBLOCK 1
147# endif
148# define SANITIZER_USE_GETRANDOM 1
149# else
150# define SANITIZER_USE_GETRANDOM 0
151# endif // SANITIZER_LINUX && defined(__NR_getrandom)
152
153# if SANITIZER_FREEBSD
154# define SANITIZER_USE_GETENTROPY 1
155# endif
156156
157157namespace __sanitizer {
158158
......@@ -160,6 +160,7 @@ void SetSigProcMask(__sanitizer_sigset_t *set, __sanitizer_sigset_t *oldset) {
160160 CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, set, oldset));
161161}
162162
163// Block asynchronous signals
163164void BlockSignals(__sanitizer_sigset_t *oldset) {
164165 __sanitizer_sigset_t set;
165166 internal_sigfillset(&set);
......@@ -174,7 +175,17 @@ void BlockSignals(__sanitizer_sigset_t *oldset) {
174175 // If this signal is blocked, such calls cannot be handled and the process may
175176 // hang.
176177 internal_sigdelset(&set, 31);
178
179 // Don't block synchronous signals
180 internal_sigdelset(&set, SIGSEGV);
181 internal_sigdelset(&set, SIGBUS);
182 internal_sigdelset(&set, SIGILL);
183 internal_sigdelset(&set, SIGTRAP);
184 internal_sigdelset(&set, SIGABRT);
185 internal_sigdelset(&set, SIGFPE);
186 internal_sigdelset(&set, SIGPIPE);
177187# endif
188
178189 SetSigProcMask(&set, oldset);
179190}
180191
......@@ -203,33 +214,33 @@ ScopedBlockSignals::~ScopedBlockSignals() { SetSigProcMask(&saved_, nullptr); }
203214# endif
204215
205216// --------------- sanitizer_libc.h
206#if !SANITIZER_SOLARIS && !SANITIZER_NETBSD
207#if !SANITIZER_S390
217# if !SANITIZER_SOLARIS && !SANITIZER_NETBSD
218# if !SANITIZER_S390
208219uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd,
209220 u64 offset) {
210#if SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS
221# if SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS
211222 return internal_syscall(SYSCALL(mmap), (uptr)addr, length, prot, flags, fd,
212223 offset);
213#else
224# else
214225 // mmap2 specifies file offset in 4096-byte units.
215226 CHECK(IsAligned(offset, 4096));
216227 return internal_syscall(SYSCALL(mmap2), addr, length, prot, flags, fd,
217 offset / 4096);
218#endif
228 (OFF_T)(offset / 4096));
229# endif
219230}
220#endif // !SANITIZER_S390
231# endif // !SANITIZER_S390
221232
222233uptr internal_munmap(void *addr, uptr length) {
223234 return internal_syscall(SYSCALL(munmap), (uptr)addr, length);
224235}
225236
226#if SANITIZER_LINUX
237# if SANITIZER_LINUX
227238uptr internal_mremap(void *old_address, uptr old_size, uptr new_size, int flags,
228239 void *new_address) {
229240 return internal_syscall(SYSCALL(mremap), (uptr)old_address, old_size,
230241 new_size, flags, (uptr)new_address);
231242}
232#endif
243# endif
233244
234245int internal_mprotect(void *addr, uptr length, int prot) {
235246 return internal_syscall(SYSCALL(mprotect), (uptr)addr, length, prot);
......@@ -239,25 +250,23 @@ int internal_madvise(uptr addr, uptr length, int advice) {
239250 return internal_syscall(SYSCALL(madvise), addr, length, advice);
240251}
241252
242uptr internal_close(fd_t fd) {
243 return internal_syscall(SYSCALL(close), fd);
244}
253uptr internal_close(fd_t fd) { return internal_syscall(SYSCALL(close), fd); }
245254
246255uptr internal_open(const char *filename, int flags) {
247256# if SANITIZER_LINUX
248257 return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags);
249#else
258# else
250259 return internal_syscall(SYSCALL(open), (uptr)filename, flags);
251#endif
260# endif
252261}
253262
254263uptr internal_open(const char *filename, int flags, u32 mode) {
255264# if SANITIZER_LINUX
256265 return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags,
257266 mode);
258#else
267# else
259268 return internal_syscall(SYSCALL(open), (uptr)filename, flags, mode);
260#endif
269# endif
261270}
262271
263272uptr internal_read(fd_t fd, void *buf, uptr count) {
......@@ -276,12 +285,12 @@ uptr internal_write(fd_t fd, const void *buf, uptr count) {
276285
277286uptr internal_ftruncate(fd_t fd, uptr size) {
278287 sptr res;
279 HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(ftruncate), fd,
280 (OFF_T)size));
288 HANDLE_EINTR(res,
289 (sptr)internal_syscall(SYSCALL(ftruncate), fd, (OFF_T)size));
281290 return res;
282291}
283292
284#if (!SANITIZER_LINUX_USES_64BIT_SYSCALLS || SANITIZER_SPARC) && SANITIZER_LINUX
293# if !SANITIZER_LINUX_USES_64BIT_SYSCALLS && SANITIZER_LINUX
285294static void stat64_to_stat(struct stat64 *in, struct stat *out) {
286295 internal_memset(out, 0, sizeof(*out));
287296 out->st_dev = in->st_dev;
......@@ -298,9 +307,9 @@ static void stat64_to_stat(struct stat64 *in, struct stat *out) {
298307 out->st_mtime = in->st_mtime;
299308 out->st_ctime = in->st_ctime;
300309}
301#endif
310# endif
302311
303#if SANITIZER_LINUX && defined(__loongarch__)
312# if SANITIZER_LINUX && defined(__loongarch__)
304313static void statx_to_stat(struct statx *in, struct stat *out) {
305314 internal_memset(out, 0, sizeof(*out));
306315 out->st_dev = makedev(in->stx_dev_major, in->stx_dev_minor);
......@@ -320,27 +329,32 @@ static void statx_to_stat(struct statx *in, struct stat *out) {
320329 out->st_ctime = in->stx_ctime.tv_sec;
321330 out->st_ctim.tv_nsec = in->stx_ctime.tv_nsec;
322331}
323#endif
332# endif
324333
325#if SANITIZER_MIPS64
334# if SANITIZER_MIPS64 || SANITIZER_SPARC64
335# if SANITIZER_MIPS64
336typedef struct kernel_stat kstat_t;
337# else
338typedef struct kernel_stat64 kstat_t;
339# endif
326340// Undefine compatibility macros from <sys/stat.h>
327341// so that they would not clash with the kernel_stat
328342// st_[a|m|c]time fields
329#if !SANITIZER_GO
330#undef st_atime
331#undef st_mtime
332#undef st_ctime
333#endif
334#if defined(SANITIZER_ANDROID)
343# if !SANITIZER_GO
344# undef st_atime
345# undef st_mtime
346# undef st_ctime
347# endif
348# if defined(SANITIZER_ANDROID)
335349// Bionic sys/stat.h defines additional macros
336350// for compatibility with the old NDKs and
337351// they clash with the kernel_stat structure
338352// st_[a|m|c]time_nsec fields.
339#undef st_atime_nsec
340#undef st_mtime_nsec
341#undef st_ctime_nsec
342#endif
343static void kernel_stat_to_stat(struct kernel_stat *in, struct stat *out) {
353# undef st_atime_nsec
354# undef st_mtime_nsec
355# undef st_ctime_nsec
356# endif
357static void kernel_stat_to_stat(kstat_t *in, struct stat *out) {
344358 internal_memset(out, 0, sizeof(*out));
345359 out->st_dev = in->st_dev;
346360 out->st_ino = in->st_ino;
......@@ -352,96 +366,113 @@ static void kernel_stat_to_stat(struct kernel_stat *in, struct stat *out) {
352366 out->st_size = in->st_size;
353367 out->st_blksize = in->st_blksize;
354368 out->st_blocks = in->st_blocks;
355#if defined(__USE_MISC) || \
356 defined(__USE_XOPEN2K8) || \
357 defined(SANITIZER_ANDROID)
369# if defined(__USE_MISC) || defined(__USE_XOPEN2K8) || \
370 defined(SANITIZER_ANDROID)
358371 out->st_atim.tv_sec = in->st_atime;
359372 out->st_atim.tv_nsec = in->st_atime_nsec;
360373 out->st_mtim.tv_sec = in->st_mtime;
361374 out->st_mtim.tv_nsec = in->st_mtime_nsec;
362375 out->st_ctim.tv_sec = in->st_ctime;
363376 out->st_ctim.tv_nsec = in->st_ctime_nsec;
364#else
377# else
365378 out->st_atime = in->st_atime;
366379 out->st_atimensec = in->st_atime_nsec;
367380 out->st_mtime = in->st_mtime;
368381 out->st_mtimensec = in->st_mtime_nsec;
369382 out->st_ctime = in->st_ctime;
370383 out->st_atimensec = in->st_ctime_nsec;
371#endif
384# endif
372385}
373#endif
386# endif
374387
375388uptr internal_stat(const char *path, void *buf) {
376# if SANITIZER_FREEBSD
389# if SANITIZER_FREEBSD
377390 return internal_syscall(SYSCALL(fstatat), AT_FDCWD, (uptr)path, (uptr)buf, 0);
378# elif SANITIZER_LINUX
379# if defined(__loongarch__)
391# elif SANITIZER_LINUX
392# if defined(__loongarch__)
380393 struct statx bufx;
381394 int res = internal_syscall(SYSCALL(statx), AT_FDCWD, (uptr)path,
382395 AT_NO_AUTOMOUNT, STATX_BASIC_STATS, (uptr)&bufx);
383396 statx_to_stat(&bufx, (struct stat *)buf);
384397 return res;
385# elif (SANITIZER_WORDSIZE == 64 || SANITIZER_X32 || \
386 (defined(__mips__) && _MIPS_SIM == _ABIN32)) && \
387 !SANITIZER_SPARC
398# elif (SANITIZER_WORDSIZE == 64 || SANITIZER_X32 || \
399 (defined(__mips__) && _MIPS_SIM == _ABIN32)) && \
400 !SANITIZER_SPARC
388401 return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf,
389402 0);
390# else
403# elif SANITIZER_SPARC64
404 kstat_t buf64;
405 int res = internal_syscall(SYSCALL(fstatat64), AT_FDCWD, (uptr)path,
406 (uptr)&buf64, 0);
407 kernel_stat_to_stat(&buf64, (struct stat *)buf);
408 return res;
409# else
391410 struct stat64 buf64;
392411 int res = internal_syscall(SYSCALL(fstatat64), AT_FDCWD, (uptr)path,
393412 (uptr)&buf64, 0);
394413 stat64_to_stat(&buf64, (struct stat *)buf);
395414 return res;
396# endif
397# else
415# endif
416# else
398417 struct stat64 buf64;
399418 int res = internal_syscall(SYSCALL(stat64), path, &buf64);
400419 stat64_to_stat(&buf64, (struct stat *)buf);
401420 return res;
402# endif
421# endif
403422}
404423
405424uptr internal_lstat(const char *path, void *buf) {
406# if SANITIZER_FREEBSD
425# if SANITIZER_FREEBSD
407426 return internal_syscall(SYSCALL(fstatat), AT_FDCWD, (uptr)path, (uptr)buf,
408427 AT_SYMLINK_NOFOLLOW);
409# elif SANITIZER_LINUX
410# if defined(__loongarch__)
428# elif SANITIZER_LINUX
429# if defined(__loongarch__)
411430 struct statx bufx;
412431 int res = internal_syscall(SYSCALL(statx), AT_FDCWD, (uptr)path,
413432 AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT,
414433 STATX_BASIC_STATS, (uptr)&bufx);
415434 statx_to_stat(&bufx, (struct stat *)buf);
416435 return res;
417# elif (defined(_LP64) || SANITIZER_X32 || \
418 (defined(__mips__) && _MIPS_SIM == _ABIN32)) && \
419 !SANITIZER_SPARC
436# elif (defined(_LP64) || SANITIZER_X32 || \
437 (defined(__mips__) && _MIPS_SIM == _ABIN32)) && \
438 !SANITIZER_SPARC
420439 return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf,
421440 AT_SYMLINK_NOFOLLOW);
422# else
441# elif SANITIZER_SPARC64
442 kstat_t buf64;
443 int res = internal_syscall(SYSCALL(fstatat64), AT_FDCWD, (uptr)path,
444 (uptr)&buf64, AT_SYMLINK_NOFOLLOW);
445 kernel_stat_to_stat(&buf64, (struct stat *)buf);
446 return res;
447# else
423448 struct stat64 buf64;
424449 int res = internal_syscall(SYSCALL(fstatat64), AT_FDCWD, (uptr)path,
425450 (uptr)&buf64, AT_SYMLINK_NOFOLLOW);
426451 stat64_to_stat(&buf64, (struct stat *)buf);
427452 return res;
428# endif
429# else
453# endif
454# else
430455 struct stat64 buf64;
431456 int res = internal_syscall(SYSCALL(lstat64), path, &buf64);
432457 stat64_to_stat(&buf64, (struct stat *)buf);
433458 return res;
434# endif
459# endif
435460}
436461
437462uptr internal_fstat(fd_t fd, void *buf) {
438#if SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS
439#if SANITIZER_MIPS64
463# if SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS
464# if SANITIZER_MIPS64
440465 // For mips64, fstat syscall fills buffer in the format of kernel_stat
441 struct kernel_stat kbuf;
466 kstat_t kbuf;
442467 int res = internal_syscall(SYSCALL(fstat), fd, &kbuf);
443468 kernel_stat_to_stat(&kbuf, (struct stat *)buf);
444469 return res;
470# elif SANITIZER_LINUX && SANITIZER_SPARC64
471 // For sparc64, fstat64 syscall fills buffer in the format of kernel_stat64
472 kstat_t kbuf;
473 int res = internal_syscall(SYSCALL(fstat64), fd, &kbuf);
474 kernel_stat_to_stat(&kbuf, (struct stat *)buf);
475 return res;
445476# elif SANITIZER_LINUX && defined(__loongarch__)
446477 struct statx bufx;
447478 int res = internal_syscall(SYSCALL(statx), fd, "", AT_EMPTY_PATH,
......@@ -451,12 +482,12 @@ uptr internal_fstat(fd_t fd, void *buf) {
451482# else
452483 return internal_syscall(SYSCALL(fstat), fd, (uptr)buf);
453484# endif
454#else
485# else
455486 struct stat64 buf64;
456487 int res = internal_syscall(SYSCALL(fstat64), fd, &buf64);
457488 stat64_to_stat(&buf64, (struct stat *)buf);
458489 return res;
459#endif
490# endif
460491}
461492
462493uptr internal_filesize(fd_t fd) {
......@@ -466,50 +497,46 @@ uptr internal_filesize(fd_t fd) {
466497 return (uptr)st.st_size;
467498}
468499
469uptr internal_dup(int oldfd) {
470 return internal_syscall(SYSCALL(dup), oldfd);
471}
500uptr internal_dup(int oldfd) { return internal_syscall(SYSCALL(dup), oldfd); }
472501
473502uptr internal_dup2(int oldfd, int newfd) {
474503# if SANITIZER_LINUX
475504 return internal_syscall(SYSCALL(dup3), oldfd, newfd, 0);
476#else
505# else
477506 return internal_syscall(SYSCALL(dup2), oldfd, newfd);
478#endif
507# endif
479508}
480509
481510uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
482511# if SANITIZER_LINUX
483512 return internal_syscall(SYSCALL(readlinkat), AT_FDCWD, (uptr)path, (uptr)buf,
484513 bufsize);
485#else
514# else
486515 return internal_syscall(SYSCALL(readlink), (uptr)path, (uptr)buf, bufsize);
487#endif
516# endif
488517}
489518
490519uptr internal_unlink(const char *path) {
491520# if SANITIZER_LINUX
492521 return internal_syscall(SYSCALL(unlinkat), AT_FDCWD, (uptr)path, 0);
493#else
522# else
494523 return internal_syscall(SYSCALL(unlink), (uptr)path);
495#endif
524# endif
496525}
497526
498527uptr internal_rename(const char *oldpath, const char *newpath) {
499# if (defined(__riscv) || defined(__loongarch__)) && defined(__linux__)
528# if (defined(__riscv) || defined(__loongarch__)) && defined(__linux__)
500529 return internal_syscall(SYSCALL(renameat2), AT_FDCWD, (uptr)oldpath, AT_FDCWD,
501530 (uptr)newpath, 0);
502# elif SANITIZER_LINUX
531# elif SANITIZER_LINUX
503532 return internal_syscall(SYSCALL(renameat), AT_FDCWD, (uptr)oldpath, AT_FDCWD,
504533 (uptr)newpath);
505# else
534# else
506535 return internal_syscall(SYSCALL(rename), (uptr)oldpath, (uptr)newpath);
507# endif
536# endif
508537}
509538
510uptr internal_sched_yield() {
511 return internal_syscall(SYSCALL(sched_yield));
512}
539uptr internal_sched_yield() { return internal_syscall(SYSCALL(sched_yield)); }
513540
514541void internal_usleep(u64 useconds) {
515542 struct timespec ts;
......@@ -523,18 +550,18 @@ uptr internal_execve(const char *filename, char *const argv[],
523550 return internal_syscall(SYSCALL(execve), (uptr)filename, (uptr)argv,
524551 (uptr)envp);
525552}
526#endif // !SANITIZER_SOLARIS && !SANITIZER_NETBSD
553# endif // !SANITIZER_SOLARIS && !SANITIZER_NETBSD
527554
528#if !SANITIZER_NETBSD
555# if !SANITIZER_NETBSD
529556void internal__exit(int exitcode) {
530#if SANITIZER_FREEBSD || SANITIZER_SOLARIS
557# if SANITIZER_FREEBSD || SANITIZER_SOLARIS
531558 internal_syscall(SYSCALL(exit), exitcode);
532#else
559# else
533560 internal_syscall(SYSCALL(exit_group), exitcode);
534#endif
561# endif
535562 Die(); // Unreachable.
536563}
537#endif // !SANITIZER_NETBSD
564# endif // !SANITIZER_NETBSD
538565
539566// ----------------- sanitizer_common.h
540567bool FileExists(const char *filename) {
......@@ -556,30 +583,32 @@ bool DirExists(const char *path) {
556583
557584# if !SANITIZER_NETBSD
558585tid_t GetTid() {
559#if SANITIZER_FREEBSD
586# if SANITIZER_FREEBSD
560587 long Tid;
561588 thr_self(&Tid);
562589 return Tid;
563#elif SANITIZER_SOLARIS
590# elif SANITIZER_SOLARIS
564591 return thr_self();
565#else
592# else
566593 return internal_syscall(SYSCALL(gettid));
567#endif
594# endif
568595}
569596
570597int TgKill(pid_t pid, tid_t tid, int sig) {
571#if SANITIZER_LINUX
598# if SANITIZER_LINUX
572599 return internal_syscall(SYSCALL(tgkill), pid, tid, sig);
573#elif SANITIZER_FREEBSD
600# elif SANITIZER_FREEBSD
574601 return internal_syscall(SYSCALL(thr_kill2), pid, tid, sig);
575#elif SANITIZER_SOLARIS
602# elif SANITIZER_SOLARIS
576603 (void)pid;
577 return thr_kill(tid, sig);
578#endif
604 errno = thr_kill(tid, sig);
605 // TgKill is expected to return -1 on error, not an errno.
606 return errno != 0 ? -1 : 0;
607# endif
579608}
580#endif
609# endif
581610
582#if SANITIZER_GLIBC
611# if SANITIZER_GLIBC
583612u64 NanoTime() {
584613 kernel_timeval tv;
585614 internal_memset(&tv, 0, sizeof(tv));
......@@ -590,19 +619,19 @@ u64 NanoTime() {
590619uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp) {
591620 return internal_syscall(SYSCALL(clock_gettime), clk_id, tp);
592621}
593#elif !SANITIZER_SOLARIS && !SANITIZER_NETBSD
622# elif !SANITIZER_SOLARIS && !SANITIZER_NETBSD
594623u64 NanoTime() {
595624 struct timespec ts;
596625 clock_gettime(CLOCK_REALTIME, &ts);
597626 return (u64)ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec;
598627}
599#endif
628# endif
600629
601630// Like getenv, but reads env directly from /proc (on Linux) or parses the
602631// 'environ' array (on some others) and does not use libc. This function
603632// should be called first inside __asan_init.
604633const char *GetEnv(const char *name) {
605#if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_SOLARIS
634# if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_SOLARIS
606635 if (::environ != 0) {
607636 uptr NameLen = internal_strlen(name);
608637 for (char **Env = ::environ; *Env != 0; Env++) {
......@@ -611,7 +640,7 @@ const char *GetEnv(const char *name) {
611640 }
612641 }
613642 return 0; // Not found.
614#elif SANITIZER_LINUX
643# elif SANITIZER_LINUX
615644 static char *environ;
616645 static uptr len;
617646 static bool inited;
......@@ -621,13 +650,13 @@ const char *GetEnv(const char *name) {
621650 if (!ReadFileToBuffer("/proc/self/environ", &environ, &environ_size, &len))
622651 environ = nullptr;
623652 }
624 if (!environ || len == 0) return nullptr;
653 if (!environ || len == 0)
654 return nullptr;
625655 uptr namelen = internal_strlen(name);
626656 const char *p = environ;
627657 while (*p != '\0') { // will happen at the \0\0 that terminates the buffer
628658 // proc file has the format NAME=value\0NAME=value\0NAME=value\0...
629 const char* endp =
630 (char*)internal_memchr(p, '\0', len - (p - environ));
659 const char *endp = (char *)internal_memchr(p, '\0', len - (p - environ));
631660 if (!endp) // this entry isn't NUL terminated
632661 return nullptr;
633662 else if (!internal_memcmp(p, name, namelen) && p[namelen] == '=') // Match.
......@@ -635,18 +664,18 @@ const char *GetEnv(const char *name) {
635664 p = endp + 1;
636665 }
637666 return nullptr; // Not found.
638#else
639#error "Unsupported platform"
640#endif
667# else
668# error "Unsupported platform"
669# endif
641670}
642671
643#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD && !SANITIZER_GO
672# if !SANITIZER_FREEBSD && !SANITIZER_NETBSD && !SANITIZER_GO
644673extern "C" {
645674SANITIZER_WEAK_ATTRIBUTE extern void *__libc_stack_end;
646675}
647#endif
676# endif
648677
649#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
678# if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
650679static void ReadNullSepFileToArray(const char *path, char ***arr,
651680 int arr_size) {
652681 char *buff;
......@@ -659,20 +688,21 @@ static void ReadNullSepFileToArray(const char *path, char ***arr,
659688 }
660689 (*arr)[0] = buff;
661690 int count, i;
662 for (count = 1, i = 1; ; i++) {
691 for (count = 1, i = 1;; i++) {
663692 if (buff[i] == 0) {
664 if (buff[i+1] == 0) break;
665 (*arr)[count] = &buff[i+1];
693 if (buff[i + 1] == 0)
694 break;
695 (*arr)[count] = &buff[i + 1];
666696 CHECK_LE(count, arr_size - 1); // FIXME: make this more flexible.
667697 count++;
668698 }
669699 }
670700 (*arr)[count] = nullptr;
671701}
672#endif
702# endif
673703
674704static void GetArgsAndEnv(char ***argv, char ***envp) {
675#if SANITIZER_FREEBSD
705# if SANITIZER_FREEBSD
676706 // On FreeBSD, retrieving the argument and environment arrays is done via the
677707 // kern.ps_strings sysctl, which returns a pointer to a structure containing
678708 // this information. See also <sys/exec.h>.
......@@ -684,30 +714,30 @@ static void GetArgsAndEnv(char ***argv, char ***envp) {
684714 }
685715 *argv = pss->ps_argvstr;
686716 *envp = pss->ps_envstr;
687#elif SANITIZER_NETBSD
717# elif SANITIZER_NETBSD
688718 *argv = __ps_strings->ps_argvstr;
689719 *envp = __ps_strings->ps_envstr;
690#else // SANITIZER_FREEBSD
691#if !SANITIZER_GO
720# else // SANITIZER_FREEBSD
721# if !SANITIZER_GO
692722 if (&__libc_stack_end) {
693 uptr* stack_end = (uptr*)__libc_stack_end;
723 uptr *stack_end = (uptr *)__libc_stack_end;
694724 // Normally argc can be obtained from *stack_end, however, on ARM glibc's
695725 // _start clobbers it:
696726 // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/arm/start.S;hb=refs/heads/release/2.31/master#l75
697727 // Do not special-case ARM and infer argc from argv everywhere.
698728 int argc = 0;
699729 while (stack_end[argc + 1]) argc++;
700 *argv = (char**)(stack_end + 1);
701 *envp = (char**)(stack_end + argc + 2);
730 *argv = (char **)(stack_end + 1);
731 *envp = (char **)(stack_end + argc + 2);
702732 } else {
703#endif // !SANITIZER_GO
733# endif // !SANITIZER_GO
704734 static const int kMaxArgv = 2000, kMaxEnvp = 2000;
705735 ReadNullSepFileToArray("/proc/self/cmdline", argv, kMaxArgv);
706736 ReadNullSepFileToArray("/proc/self/environ", envp, kMaxEnvp);
707#if !SANITIZER_GO
737# if !SANITIZER_GO
708738 }
709#endif // !SANITIZER_GO
710#endif // SANITIZER_FREEBSD
739# endif // !SANITIZER_GO
740# endif // SANITIZER_FREEBSD
711741}
712742
713743char **GetArgv() {
......@@ -722,12 +752,12 @@ char **GetEnviron() {
722752 return envp;
723753}
724754
725#if !SANITIZER_SOLARIS
755# if !SANITIZER_SOLARIS
726756void FutexWait(atomic_uint32_t *p, u32 cmp) {
727757# if SANITIZER_FREEBSD
728758 _umtx_op(p, UMTX_OP_WAIT_UINT, cmp, 0, 0);
729759# elif SANITIZER_NETBSD
730 sched_yield(); /* No userspace futex-like synchronization */
760 sched_yield(); /* No userspace futex-like synchronization */
731761# else
732762 internal_syscall(SYSCALL(futex), (uptr)p, FUTEX_WAIT_PRIVATE, cmp, 0, 0, 0);
733763# endif
......@@ -737,7 +767,7 @@ void FutexWake(atomic_uint32_t *p, u32 count) {
737767# if SANITIZER_FREEBSD
738768 _umtx_op(p, UMTX_OP_WAKE, count, 0, 0);
739769# elif SANITIZER_NETBSD
740 /* No userspace futex-like synchronization */
770 /* No userspace futex-like synchronization */
741771# else
742772 internal_syscall(SYSCALL(futex), (uptr)p, FUTEX_WAKE_PRIVATE, count, 0, 0, 0);
743773# endif
......@@ -749,26 +779,26 @@ void FutexWake(atomic_uint32_t *p, u32 count) {
749779// The actual size of this structure is specified by d_reclen.
750780// Note that getdents64 uses a different structure format. We only provide the
751781// 32-bit syscall here.
752#if SANITIZER_NETBSD
782# if SANITIZER_NETBSD
753783// Not used
754#else
784# else
755785struct linux_dirent {
756786# if SANITIZER_X32 || SANITIZER_LINUX
757787 u64 d_ino;
758788 u64 d_off;
759789# else
760 unsigned long d_ino;
761 unsigned long d_off;
790 unsigned long d_ino;
791 unsigned long d_off;
762792# endif
763 unsigned short d_reclen;
793 unsigned short d_reclen;
764794# if SANITIZER_LINUX
765 unsigned char d_type;
795 unsigned char d_type;
766796# endif
767 char d_name[256];
797 char d_name[256];
768798};
769#endif
799# endif
770800
771#if !SANITIZER_SOLARIS && !SANITIZER_NETBSD
801# if !SANITIZER_SOLARIS && !SANITIZER_NETBSD
772802// Syscall wrappers.
773803uptr internal_ptrace(int request, int pid, void *addr, void *data) {
774804 return internal_syscall(SYSCALL(ptrace), request, pid, (uptr)addr,
......@@ -780,24 +810,20 @@ uptr internal_waitpid(int pid, int *status, int options) {
780810 0 /* rusage */);
781811}
782812
783uptr internal_getpid() {
784 return internal_syscall(SYSCALL(getpid));
785}
813uptr internal_getpid() { return internal_syscall(SYSCALL(getpid)); }
786814
787uptr internal_getppid() {
788 return internal_syscall(SYSCALL(getppid));
789}
815uptr internal_getppid() { return internal_syscall(SYSCALL(getppid)); }
790816
791817int internal_dlinfo(void *handle, int request, void *p) {
792#if SANITIZER_FREEBSD
818# if SANITIZER_FREEBSD
793819 return dlinfo(handle, request, p);
794#else
820# else
795821 UNIMPLEMENTED();
796#endif
822# endif
797823}
798824
799825uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) {
800#if SANITIZER_FREEBSD
826# if SANITIZER_FREEBSD
801827 return internal_syscall(SYSCALL(getdirentries), fd, (uptr)dirp, count, NULL);
802828# elif SANITIZER_LINUX
803829 return internal_syscall(SYSCALL(getdents64), fd, (uptr)dirp, count);
......@@ -810,7 +836,7 @@ uptr internal_lseek(fd_t fd, OFF_T offset, int whence) {
810836 return internal_syscall(SYSCALL(lseek), fd, offset, whence);
811837}
812838
813#if SANITIZER_LINUX
839# if SANITIZER_LINUX
814840uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) {
815841 return internal_syscall(SYSCALL(prctl), option, arg2, arg3, arg4, arg5);
816842}
......@@ -827,10 +853,16 @@ uptr internal_sigaltstack(const void *ss, void *oss) {
827853 return internal_syscall(SYSCALL(sigaltstack), (uptr)ss, (uptr)oss);
828854}
829855
856extern "C" pid_t __fork(void);
857
830858int internal_fork() {
831859# if SANITIZER_LINUX
832860# if SANITIZER_S390
833861 return internal_syscall(SYSCALL(clone), 0, SIGCHLD);
862# elif SANITIZER_SPARC
863 // The clone syscall interface on SPARC differs massively from the rest,
864 // so fall back to __fork.
865 return __fork();
834866# else
835867 return internal_syscall(SYSCALL(clone), SIGCHLD, 0);
836868# endif
......@@ -839,7 +871,7 @@ int internal_fork() {
839871# endif
840872}
841873
842#if SANITIZER_FREEBSD
874# if SANITIZER_FREEBSD
843875int internal_sysctl(const int *name, unsigned int namelen, void *oldp,
844876 uptr *oldlenp, const void *newp, uptr newlen) {
845877 return internal_syscall(SYSCALL(__sysctl), name, namelen, oldp,
......@@ -854,11 +886,11 @@ int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp,
854886 // followed by sysctl(). To avoid calling the intercepted version and
855887 // asserting if this happens during startup, call the real sysctlnametomib()
856888 // followed by internal_sysctl() if the syscall is not available.
857#ifdef SYS___sysctlbyname
889# ifdef SYS___sysctlbyname
858890 return internal_syscall(SYSCALL(__sysctlbyname), sname,
859891 internal_strlen(sname), oldp, (size_t *)oldlenp, newp,
860892 (size_t)newlen);
861#else
893# else
862894 static decltype(sysctlnametomib) *real_sysctlnametomib = nullptr;
863895 if (!real_sysctlnametomib)
864896 real_sysctlnametomib =
......@@ -870,12 +902,12 @@ int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp,
870902 if (real_sysctlnametomib(sname, oid, &len) == -1)
871903 return (-1);
872904 return internal_sysctl(oid, len, oldp, oldlenp, newp, newlen);
873#endif
905# endif
874906}
875#endif
907# endif
876908
877#if SANITIZER_LINUX
878#define SA_RESTORER 0x04000000
909# if SANITIZER_LINUX
910# define SA_RESTORER 0x04000000
879911// Doesn't set sa_restorer if the caller did not set it, so use with caution
880912//(see below).
881913int internal_sigaction_norestorer(int signum, const void *act, void *oldact) {
......@@ -899,15 +931,15 @@ int internal_sigaction_norestorer(int signum, const void *act, void *oldact) {
899931 // rt_sigaction, so we need to do the same (we'll need to reimplement the
900932 // restorers; for x86_64 the restorer address can be obtained from
901933 // oldact->sa_restorer upon a call to sigaction(xxx, NULL, oldact).
902#if !SANITIZER_ANDROID || !SANITIZER_MIPS32
934# if !SANITIZER_ANDROID || !SANITIZER_MIPS32
903935 k_act.sa_restorer = u_act->sa_restorer;
904#endif
936# endif
905937 }
906938
907939 uptr result = internal_syscall(SYSCALL(rt_sigaction), (uptr)signum,
908 (uptr)(u_act ? &k_act : nullptr),
909 (uptr)(u_oldact ? &k_oldact : nullptr),
910 (uptr)sizeof(__sanitizer_kernel_sigset_t));
940 (uptr)(u_act ? &k_act : nullptr),
941 (uptr)(u_oldact ? &k_oldact : nullptr),
942 (uptr)sizeof(__sanitizer_kernel_sigset_t));
911943
912944 if ((result == 0) && u_oldact) {
913945 u_oldact->handler = k_oldact.handler;
......@@ -915,24 +947,24 @@ int internal_sigaction_norestorer(int signum, const void *act, void *oldact) {
915947 internal_memcpy(&u_oldact->sa_mask, &k_oldact.sa_mask,
916948 sizeof(__sanitizer_kernel_sigset_t));
917949 u_oldact->sa_flags = k_oldact.sa_flags;
918#if !SANITIZER_ANDROID || !SANITIZER_MIPS32
950# if !SANITIZER_ANDROID || !SANITIZER_MIPS32
919951 u_oldact->sa_restorer = k_oldact.sa_restorer;
920#endif
952# endif
921953 }
922954 return result;
923955}
924#endif // SANITIZER_LINUX
956# endif // SANITIZER_LINUX
925957
926958uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set,
927959 __sanitizer_sigset_t *oldset) {
928#if SANITIZER_FREEBSD
960# if SANITIZER_FREEBSD
929961 return internal_syscall(SYSCALL(sigprocmask), how, set, oldset);
930#else
962# else
931963 __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set;
932964 __sanitizer_kernel_sigset_t *k_oldset = (__sanitizer_kernel_sigset_t *)oldset;
933965 return internal_syscall(SYSCALL(rt_sigprocmask), (uptr)how, (uptr)k_set,
934966 (uptr)k_oldset, sizeof(__sanitizer_kernel_sigset_t));
935#endif
967# endif
936968}
937969
938970void internal_sigfillset(__sanitizer_sigset_t *set) {
......@@ -943,7 +975,7 @@ void internal_sigemptyset(__sanitizer_sigset_t *set) {
943975 internal_memset(set, 0, sizeof(*set));
944976}
945977
946#if SANITIZER_LINUX
978# if SANITIZER_LINUX
947979void internal_sigdelset(__sanitizer_sigset_t *set, int signum) {
948980 signum -= 1;
949981 CHECK_GE(signum, 0);
......@@ -963,7 +995,7 @@ bool internal_sigismember(__sanitizer_sigset_t *set, int signum) {
963995 const uptr bit = signum % (sizeof(k_set->sig[0]) * 8);
964996 return k_set->sig[idx] & ((uptr)1 << bit);
965997}
966#elif SANITIZER_FREEBSD
998# elif SANITIZER_FREEBSD
967999uptr internal_procctl(int type, int id, int cmd, void *data) {
9681000 return internal_syscall(SYSCALL(procctl), type, id, cmd, data);
9691001}
......@@ -977,10 +1009,10 @@ bool internal_sigismember(__sanitizer_sigset_t *set, int signum) {
9771009 sigset_t *rset = reinterpret_cast<sigset_t *>(set);
9781010 return sigismember(rset, signum);
9791011}
980#endif
981#endif // !SANITIZER_SOLARIS
1012# endif
1013# endif // !SANITIZER_SOLARIS
9821014
983#if !SANITIZER_NETBSD
1015# if !SANITIZER_NETBSD
9841016// ThreadLister implementation.
9851017ThreadLister::ThreadLister(pid_t pid) : pid_(pid), buffer_(4096) {
9861018 char task_directory_path[80];
......@@ -1067,25 +1099,26 @@ ThreadLister::~ThreadLister() {
10671099 if (!internal_iserror(descriptor_))
10681100 internal_close(descriptor_);
10691101}
1070#endif
1102# endif
10711103
1072#if SANITIZER_WORDSIZE == 32
1104# if SANITIZER_WORDSIZE == 32
10731105// Take care of unusable kernel area in top gigabyte.
10741106static uptr GetKernelAreaSize() {
1075#if SANITIZER_LINUX && !SANITIZER_X32
1107# if SANITIZER_LINUX && !SANITIZER_X32
10761108 const uptr gbyte = 1UL << 30;
10771109
10781110 // Firstly check if there are writable segments
10791111 // mapped to top gigabyte (e.g. stack).
1080 MemoryMappingLayout proc_maps(/*cache_enabled*/true);
1112 MemoryMappingLayout proc_maps(/*cache_enabled*/ true);
10811113 if (proc_maps.Error())
10821114 return 0;
10831115 MemoryMappedSegment segment;
10841116 while (proc_maps.Next(&segment)) {
1085 if ((segment.end >= 3 * gbyte) && segment.IsWritable()) return 0;
1117 if ((segment.end >= 3 * gbyte) && segment.IsWritable())
1118 return 0;
10861119 }
10871120
1088#if !SANITIZER_ANDROID
1121# if !SANITIZER_ANDROID
10891122 // Even if nothing is mapped, top Gb may still be accessible
10901123 // if we are running on 64-bit kernel.
10911124 // Uname may report misleading results if personality type
......@@ -1095,21 +1128,22 @@ static uptr GetKernelAreaSize() {
10951128 if (!(pers & PER_MASK) && internal_uname(&uname_info) == 0 &&
10961129 internal_strstr(uname_info.machine, "64"))
10971130 return 0;
1098#endif // SANITIZER_ANDROID
1131# endif // SANITIZER_ANDROID
10991132
11001133 // Top gigabyte is reserved for kernel.
11011134 return gbyte;
1102#else
1135# else
11031136 return 0;
1104#endif // SANITIZER_LINUX && !SANITIZER_X32
1137# endif // SANITIZER_LINUX && !SANITIZER_X32
11051138}
1106#endif // SANITIZER_WORDSIZE == 32
1139# endif // SANITIZER_WORDSIZE == 32
11071140
11081141uptr GetMaxVirtualAddress() {
1109#if SANITIZER_NETBSD && defined(__x86_64__)
1142# if SANITIZER_NETBSD && defined(__x86_64__)
11101143 return 0x7f7ffffff000ULL; // (0x00007f8000000000 - PAGE_SIZE)
1111#elif SANITIZER_WORDSIZE == 64
1112# if defined(__powerpc64__) || defined(__aarch64__) || defined(__loongarch__)
1144# elif SANITIZER_WORDSIZE == 64
1145# if defined(__powerpc64__) || defined(__aarch64__) || \
1146 defined(__loongarch__) || SANITIZER_RISCV64
11131147 // On PowerPC64 we have two different address space layouts: 44- and 46-bit.
11141148 // We somehow need to figure out which one we are using now and choose
11151149 // one of 0x00000fffffffffffUL and 0x00003fffffffffffUL.
......@@ -1118,97 +1152,97 @@ uptr GetMaxVirtualAddress() {
11181152 // This should (does) work for both PowerPC64 Endian modes.
11191153 // Similarly, aarch64 has multiple address space layouts: 39, 42 and 47-bit.
11201154 // loongarch64 also has multiple address space layouts: default is 47-bit.
1155 // RISC-V 64 also has multiple address space layouts: 39, 48 and 57-bit.
11211156 return (1ULL << (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1)) - 1;
1122#elif SANITIZER_RISCV64
1123 return (1ULL << 38) - 1;
1124# elif SANITIZER_MIPS64
1157# elif SANITIZER_MIPS64
11251158 return (1ULL << 40) - 1; // 0x000000ffffffffffUL;
1126# elif defined(__s390x__)
1159# elif defined(__s390x__)
11271160 return (1ULL << 53) - 1; // 0x001fffffffffffffUL;
1128#elif defined(__sparc__)
1161# elif defined(__sparc__)
11291162 return ~(uptr)0;
1130# else
1163# else
11311164 return (1ULL << 47) - 1; // 0x00007fffffffffffUL;
1132# endif
1133#else // SANITIZER_WORDSIZE == 32
1134# if defined(__s390__)
1165# endif
1166# else // SANITIZER_WORDSIZE == 32
1167# if defined(__s390__)
11351168 return (1ULL << 31) - 1; // 0x7fffffff;
1136# else
1169# else
11371170 return (1ULL << 32) - 1; // 0xffffffff;
1138# endif
1139#endif // SANITIZER_WORDSIZE
1171# endif
1172# endif // SANITIZER_WORDSIZE
11401173}
11411174
11421175uptr GetMaxUserVirtualAddress() {
11431176 uptr addr = GetMaxVirtualAddress();
1144#if SANITIZER_WORDSIZE == 32 && !defined(__s390__)
1177# if SANITIZER_WORDSIZE == 32 && !defined(__s390__)
11451178 if (!common_flags()->full_address_space)
11461179 addr -= GetKernelAreaSize();
11471180 CHECK_LT(reinterpret_cast<uptr>(&addr), addr);
1148#endif
1181# endif
11491182 return addr;
11501183}
11511184
1152#if !SANITIZER_ANDROID
1185# if !SANITIZER_ANDROID || defined(__aarch64__)
11531186uptr GetPageSize() {
1154#if SANITIZER_LINUX && (defined(__x86_64__) || defined(__i386__)) && \
1155 defined(EXEC_PAGESIZE)
1187# if SANITIZER_LINUX && (defined(__x86_64__) || defined(__i386__)) && \
1188 defined(EXEC_PAGESIZE)
11561189 return EXEC_PAGESIZE;
1157#elif SANITIZER_FREEBSD || SANITIZER_NETBSD
1158// Use sysctl as sysconf can trigger interceptors internally.
1190# elif SANITIZER_FREEBSD || SANITIZER_NETBSD
1191 // Use sysctl as sysconf can trigger interceptors internally.
11591192 int pz = 0;
11601193 uptr pzl = sizeof(pz);
11611194 int mib[2] = {CTL_HW, HW_PAGESIZE};
11621195 int rv = internal_sysctl(mib, 2, &pz, &pzl, nullptr, 0);
11631196 CHECK_EQ(rv, 0);
11641197 return (uptr)pz;
1165#elif SANITIZER_USE_GETAUXVAL
1198# elif SANITIZER_USE_GETAUXVAL
11661199 return getauxval(AT_PAGESZ);
1167#else
1200# else
11681201 return sysconf(_SC_PAGESIZE); // EXEC_PAGESIZE may not be trustworthy.
1169#endif
1202# endif
11701203}
1171#endif // !SANITIZER_ANDROID
1204# endif
11721205
1173uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
1174#if SANITIZER_SOLARIS
1206uptr ReadBinaryName(/*out*/ char *buf, uptr buf_len) {
1207# if SANITIZER_SOLARIS
11751208 const char *default_module_name = getexecname();
11761209 CHECK_NE(default_module_name, NULL);
11771210 return internal_snprintf(buf, buf_len, "%s", default_module_name);
1178#else
1179#if SANITIZER_FREEBSD || SANITIZER_NETBSD
1180#if SANITIZER_FREEBSD
1211# else
1212# if SANITIZER_FREEBSD || SANITIZER_NETBSD
1213# if SANITIZER_FREEBSD
11811214 const int Mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
1182#else
1215# else
11831216 const int Mib[4] = {CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME};
1184#endif
1217# endif
11851218 const char *default_module_name = "kern.proc.pathname";
11861219 uptr Size = buf_len;
11871220 bool IsErr =
11881221 (internal_sysctl(Mib, ARRAY_SIZE(Mib), buf, &Size, NULL, 0) != 0);
11891222 int readlink_error = IsErr ? errno : 0;
11901223 uptr module_name_len = Size;
1191#else
1224# else
11921225 const char *default_module_name = "/proc/self/exe";
1193 uptr module_name_len = internal_readlink(
1194 default_module_name, buf, buf_len);
1226 uptr module_name_len = internal_readlink(default_module_name, buf, buf_len);
11951227 int readlink_error;
11961228 bool IsErr = internal_iserror(module_name_len, &readlink_error);
1197#endif // SANITIZER_SOLARIS
1229# endif
11981230 if (IsErr) {
11991231 // We can't read binary name for some reason, assume it's unknown.
1200 Report("WARNING: reading executable name failed with errno %d, "
1201 "some stack frames may not be symbolized\n", readlink_error);
1202 module_name_len = internal_snprintf(buf, buf_len, "%s",
1203 default_module_name);
1232 Report(
1233 "WARNING: reading executable name failed with errno %d, "
1234 "some stack frames may not be symbolized\n",
1235 readlink_error);
1236 module_name_len =
1237 internal_snprintf(buf, buf_len, "%s", default_module_name);
12041238 CHECK_LT(module_name_len, buf_len);
12051239 }
12061240 return module_name_len;
1207#endif
1241# endif
12081242}
12091243
12101244uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len) {
1211#if SANITIZER_LINUX
1245# if SANITIZER_LINUX
12121246 char *tmpbuf;
12131247 uptr tmpsize;
12141248 uptr tmplen;
......@@ -1218,7 +1252,7 @@ uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len) {
12181252 UnmapOrDie(tmpbuf, tmpsize);
12191253 return internal_strlen(buf);
12201254 }
1221#endif
1255# endif
12221256 return ReadBinaryName(buf, buf_len);
12231257}
12241258
......@@ -1228,20 +1262,22 @@ bool LibraryNameIs(const char *full_name, const char *base_name) {
12281262 // Strip path.
12291263 while (*name != '\0') name++;
12301264 while (name > full_name && *name != '/') name--;
1231 if (*name == '/') name++;
1265 if (*name == '/')
1266 name++;
12321267 uptr base_name_length = internal_strlen(base_name);
1233 if (internal_strncmp(name, base_name, base_name_length)) return false;
1268 if (internal_strncmp(name, base_name, base_name_length))
1269 return false;
12341270 return (name[base_name_length] == '-' || name[base_name_length] == '.');
12351271}
12361272
1237#if !SANITIZER_ANDROID
1273# if !SANITIZER_ANDROID
12381274// Call cb for each region mapped by map.
12391275void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)) {
12401276 CHECK_NE(map, nullptr);
1241#if !SANITIZER_FREEBSD
1277# if !SANITIZER_FREEBSD
12421278 typedef ElfW(Phdr) Elf_Phdr;
12431279 typedef ElfW(Ehdr) Elf_Ehdr;
1244#endif // !SANITIZER_FREEBSD
1280# endif // !SANITIZER_FREEBSD
12451281 char *base = (char *)map->l_addr;
12461282 Elf_Ehdr *ehdr = (Elf_Ehdr *)base;
12471283 char *phdrs = base + ehdr->e_phoff;
......@@ -1273,10 +1309,10 @@ void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)) {
12731309 }
12741310 }
12751311}
1276#endif
1312# endif
12771313
1278#if SANITIZER_LINUX
1279#if defined(__x86_64__)
1314# if SANITIZER_LINUX
1315# if defined(__x86_64__)
12801316// We cannot use glibc's clone wrapper, because it messes with the child
12811317// task's TLS. It writes the PID and TID of the child task to its thread
12821318// descriptor, but in our case the child task shares the thread descriptor with
......@@ -1295,50 +1331,46 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
12951331 register void *r8 __asm__("r8") = newtls;
12961332 register int *r10 __asm__("r10") = child_tidptr;
12971333 __asm__ __volatile__(
1298 /* %rax = syscall(%rax = SYSCALL(clone),
1299 * %rdi = flags,
1300 * %rsi = child_stack,
1301 * %rdx = parent_tidptr,
1302 * %r8 = new_tls,
1303 * %r10 = child_tidptr)
1304 */
1305 "syscall\n"
1306
1307 /* if (%rax != 0)
1308 * return;
1309 */
1310 "testq %%rax,%%rax\n"
1311 "jnz 1f\n"
1312
1313 /* In the child. Terminate unwind chain. */
1314 // XXX: We should also terminate the CFI unwind chain
1315 // here. Unfortunately clang 3.2 doesn't support the
1316 // necessary CFI directives, so we skip that part.
1317 "xorq %%rbp,%%rbp\n"
1318
1319 /* Call "fn(arg)". */
1320 "popq %%rax\n"
1321 "popq %%rdi\n"
1322 "call *%%rax\n"
1323
1324 /* Call _exit(%rax). */
1325 "movq %%rax,%%rdi\n"
1326 "movq %2,%%rax\n"
1327 "syscall\n"
1328
1329 /* Return to parent. */
1330 "1:\n"
1331 : "=a" (res)
1332 : "a"(SYSCALL(clone)), "i"(SYSCALL(exit)),
1333 "S"(child_stack),
1334 "D"(flags),
1335 "d"(parent_tidptr),
1336 "r"(r8),
1337 "r"(r10)
1338 : "memory", "r11", "rcx");
1334 /* %rax = syscall(%rax = SYSCALL(clone),
1335 * %rdi = flags,
1336 * %rsi = child_stack,
1337 * %rdx = parent_tidptr,
1338 * %r8 = new_tls,
1339 * %r10 = child_tidptr)
1340 */
1341 "syscall\n"
1342
1343 /* if (%rax != 0)
1344 * return;
1345 */
1346 "testq %%rax,%%rax\n"
1347 "jnz 1f\n"
1348
1349 /* In the child. Terminate unwind chain. */
1350 // XXX: We should also terminate the CFI unwind chain
1351 // here. Unfortunately clang 3.2 doesn't support the
1352 // necessary CFI directives, so we skip that part.
1353 "xorq %%rbp,%%rbp\n"
1354
1355 /* Call "fn(arg)". */
1356 "popq %%rax\n"
1357 "popq %%rdi\n"
1358 "call *%%rax\n"
1359
1360 /* Call _exit(%rax). */
1361 "movq %%rax,%%rdi\n"
1362 "movq %2,%%rax\n"
1363 "syscall\n"
1364
1365 /* Return to parent. */
1366 "1:\n"
1367 : "=a"(res)
1368 : "a"(SYSCALL(clone)), "i"(SYSCALL(exit)), "S"(child_stack), "D"(flags),
1369 "d"(parent_tidptr), "r"(r8), "r"(r10)
1370 : "memory", "r11", "rcx");
13391371 return res;
13401372}
1341#elif defined(__mips__)
1373# elif defined(__mips__)
13421374uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
13431375 int *parent_tidptr, void *newtls, int *child_tidptr) {
13441376 long long res;
......@@ -1353,68 +1385,63 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
13531385 // We don't have proper CFI directives here because it requires alot of code
13541386 // for very marginal benefits.
13551387 __asm__ __volatile__(
1356 /* $v0 = syscall($v0 = __NR_clone,
1357 * $a0 = flags,
1358 * $a1 = child_stack,
1359 * $a2 = parent_tidptr,
1360 * $a3 = new_tls,
1361 * $a4 = child_tidptr)
1362 */
1363 ".cprestore 16;\n"
1364 "move $4,%1;\n"
1365 "move $5,%2;\n"
1366 "move $6,%3;\n"
1367 "move $7,%4;\n"
1368 /* Store the fifth argument on stack
1369 * if we are using 32-bit abi.
1370 */
1371#if SANITIZER_WORDSIZE == 32
1372 "lw %5,16($29);\n"
1373#else
1374 "move $8,%5;\n"
1375#endif
1376 "li $2,%6;\n"
1377 "syscall;\n"
1378
1379 /* if ($v0 != 0)
1380 * return;
1381 */
1382 "bnez $2,1f;\n"
1383
1384 /* Call "fn(arg)". */
1385#if SANITIZER_WORDSIZE == 32
1386#ifdef __BIG_ENDIAN__
1387 "lw $25,4($29);\n"
1388 "lw $4,12($29);\n"
1389#else
1390 "lw $25,0($29);\n"
1391 "lw $4,8($29);\n"
1392#endif
1393#else
1394 "ld $25,0($29);\n"
1395 "ld $4,8($29);\n"
1396#endif
1397 "jal $25;\n"
1398
1399 /* Call _exit($v0). */
1400 "move $4,$2;\n"
1401 "li $2,%7;\n"
1402 "syscall;\n"
1403
1404 /* Return to parent. */
1405 "1:\n"
1406 : "=r" (res)
1407 : "r"(flags),
1408 "r"(child_stack),
1409 "r"(parent_tidptr),
1410 "r"(a3),
1411 "r"(a4),
1412 "i"(__NR_clone),
1413 "i"(__NR_exit)
1414 : "memory", "$29" );
1388 /* $v0 = syscall($v0 = __NR_clone,
1389 * $a0 = flags,
1390 * $a1 = child_stack,
1391 * $a2 = parent_tidptr,
1392 * $a3 = new_tls,
1393 * $a4 = child_tidptr)
1394 */
1395 ".cprestore 16;\n"
1396 "move $4,%1;\n"
1397 "move $5,%2;\n"
1398 "move $6,%3;\n"
1399 "move $7,%4;\n"
1400 /* Store the fifth argument on stack
1401 * if we are using 32-bit abi.
1402 */
1403# if SANITIZER_WORDSIZE == 32
1404 "lw %5,16($29);\n"
1405# else
1406 "move $8,%5;\n"
1407# endif
1408 "li $2,%6;\n"
1409 "syscall;\n"
1410
1411 /* if ($v0 != 0)
1412 * return;
1413 */
1414 "bnez $2,1f;\n"
1415
1416 /* Call "fn(arg)". */
1417# if SANITIZER_WORDSIZE == 32
1418# ifdef __BIG_ENDIAN__
1419 "lw $25,4($29);\n"
1420 "lw $4,12($29);\n"
1421# else
1422 "lw $25,0($29);\n"
1423 "lw $4,8($29);\n"
1424# endif
1425# else
1426 "ld $25,0($29);\n"
1427 "ld $4,8($29);\n"
1428# endif
1429 "jal $25;\n"
1430
1431 /* Call _exit($v0). */
1432 "move $4,$2;\n"
1433 "li $2,%7;\n"
1434 "syscall;\n"
1435
1436 /* Return to parent. */
1437 "1:\n"
1438 : "=r"(res)
1439 : "r"(flags), "r"(child_stack), "r"(parent_tidptr), "r"(a3), "r"(a4),
1440 "i"(__NR_clone), "i"(__NR_exit)
1441 : "memory", "$29");
14151442 return res;
14161443}
1417#elif SANITIZER_RISCV64
1444# elif SANITIZER_RISCV64
14181445uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
14191446 int *parent_tidptr, void *newtls, int *child_tidptr) {
14201447 if (!fn || !child_stack)
......@@ -1455,7 +1482,7 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
14551482 : "memory");
14561483 return res;
14571484}
1458#elif defined(__aarch64__)
1485# elif defined(__aarch64__)
14591486uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
14601487 int *parent_tidptr, void *newtls, int *child_tidptr) {
14611488 register long long res __asm__("x0");
......@@ -1466,47 +1493,45 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
14661493 ((unsigned long long *)child_stack)[0] = (uptr)fn;
14671494 ((unsigned long long *)child_stack)[1] = (uptr)arg;
14681495
1469 register int (*__fn)(void *) __asm__("x0") = fn;
1496 register int (*__fn)(void *) __asm__("x0") = fn;
14701497 register void *__stack __asm__("x1") = child_stack;
1471 register int __flags __asm__("x2") = flags;
1472 register void *__arg __asm__("x3") = arg;
1473 register int *__ptid __asm__("x4") = parent_tidptr;
1474 register void *__tls __asm__("x5") = newtls;
1475 register int *__ctid __asm__("x6") = child_tidptr;
1498 register int __flags __asm__("x2") = flags;
1499 register void *__arg __asm__("x3") = arg;
1500 register int *__ptid __asm__("x4") = parent_tidptr;
1501 register void *__tls __asm__("x5") = newtls;
1502 register int *__ctid __asm__("x6") = child_tidptr;
14761503
14771504 __asm__ __volatile__(
1478 "mov x0,x2\n" /* flags */
1479 "mov x2,x4\n" /* ptid */
1480 "mov x3,x5\n" /* tls */
1481 "mov x4,x6\n" /* ctid */
1482 "mov x8,%9\n" /* clone */
1483
1484 "svc 0x0\n"
1485
1486 /* if (%r0 != 0)
1487 * return %r0;
1488 */
1489 "cmp x0, #0\n"
1490 "bne 1f\n"
1491
1492 /* In the child, now. Call "fn(arg)". */
1493 "ldp x1, x0, [sp], #16\n"
1494 "blr x1\n"
1495
1496 /* Call _exit(%r0). */
1497 "mov x8, %10\n"
1498 "svc 0x0\n"
1499 "1:\n"
1500
1501 : "=r" (res)
1502 : "i"(-EINVAL),
1503 "r"(__fn), "r"(__stack), "r"(__flags), "r"(__arg),
1504 "r"(__ptid), "r"(__tls), "r"(__ctid),
1505 "i"(__NR_clone), "i"(__NR_exit)
1506 : "x30", "memory");
1505 "mov x0,x2\n" /* flags */
1506 "mov x2,x4\n" /* ptid */
1507 "mov x3,x5\n" /* tls */
1508 "mov x4,x6\n" /* ctid */
1509 "mov x8,%9\n" /* clone */
1510
1511 "svc 0x0\n"
1512
1513 /* if (%r0 != 0)
1514 * return %r0;
1515 */
1516 "cmp x0, #0\n"
1517 "bne 1f\n"
1518
1519 /* In the child, now. Call "fn(arg)". */
1520 "ldp x1, x0, [sp], #16\n"
1521 "blr x1\n"
1522
1523 /* Call _exit(%r0). */
1524 "mov x8, %10\n"
1525 "svc 0x0\n"
1526 "1:\n"
1527
1528 : "=r"(res)
1529 : "i"(-EINVAL), "r"(__fn), "r"(__stack), "r"(__flags), "r"(__arg),
1530 "r"(__ptid), "r"(__tls), "r"(__ctid), "i"(__NR_clone), "i"(__NR_exit)
1531 : "x30", "memory");
15071532 return res;
15081533}
1509#elif SANITIZER_LOONGARCH64
1534# elif SANITIZER_LOONGARCH64
15101535uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
15111536 int *parent_tidptr, void *newtls, int *child_tidptr) {
15121537 if (!fn || !child_stack)
......@@ -1544,119 +1569,110 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
15441569 : "=r"(res)
15451570 : "0"(__flags), "r"(__stack), "r"(__ptid), "r"(__ctid), "r"(__tls),
15461571 "r"(__fn), "r"(__arg), "r"(nr_clone), "i"(__NR_exit)
1547 : "memory", "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8");
1572 : "memory", "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7",
1573 "$t8");
15481574 return res;
15491575}
1550#elif defined(__powerpc64__)
1576# elif defined(__powerpc64__)
15511577uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
1552 int *parent_tidptr, void *newtls, int *child_tidptr) {
1578 int *parent_tidptr, void *newtls, int *child_tidptr) {
15531579 long long res;
15541580// Stack frame structure.
1555#if SANITIZER_PPC64V1
1556// Back chain == 0 (SP + 112)
1557// Frame (112 bytes):
1558// Parameter save area (SP + 48), 8 doublewords
1559// TOC save area (SP + 40)
1560// Link editor doubleword (SP + 32)
1561// Compiler doubleword (SP + 24)
1562// LR save area (SP + 16)
1563// CR save area (SP + 8)
1564// Back chain (SP + 0)
1565# define FRAME_SIZE 112
1566# define FRAME_TOC_SAVE_OFFSET 40
1567#elif SANITIZER_PPC64V2
1568// Back chain == 0 (SP + 32)
1569// Frame (32 bytes):
1570// TOC save area (SP + 24)
1571// LR save area (SP + 16)
1572// CR save area (SP + 8)
1573// Back chain (SP + 0)
1574# define FRAME_SIZE 32
1575# define FRAME_TOC_SAVE_OFFSET 24
1576#else
1577# error "Unsupported PPC64 ABI"
1578#endif
1581# if SANITIZER_PPC64V1
1582 // Back chain == 0 (SP + 112)
1583 // Frame (112 bytes):
1584 // Parameter save area (SP + 48), 8 doublewords
1585 // TOC save area (SP + 40)
1586 // Link editor doubleword (SP + 32)
1587 // Compiler doubleword (SP + 24)
1588 // LR save area (SP + 16)
1589 // CR save area (SP + 8)
1590 // Back chain (SP + 0)
1591# define FRAME_SIZE 112
1592# define FRAME_TOC_SAVE_OFFSET 40
1593# elif SANITIZER_PPC64V2
1594 // Back chain == 0 (SP + 32)
1595 // Frame (32 bytes):
1596 // TOC save area (SP + 24)
1597 // LR save area (SP + 16)
1598 // CR save area (SP + 8)
1599 // Back chain (SP + 0)
1600# define FRAME_SIZE 32
1601# define FRAME_TOC_SAVE_OFFSET 24
1602# else
1603# error "Unsupported PPC64 ABI"
1604# endif
15791605 if (!fn || !child_stack)
15801606 return -EINVAL;
15811607 CHECK_EQ(0, (uptr)child_stack % 16);
15821608
15831609 register int (*__fn)(void *) __asm__("r3") = fn;
1584 register void *__cstack __asm__("r4") = child_stack;
1585 register int __flags __asm__("r5") = flags;
1586 register void *__arg __asm__("r6") = arg;
1587 register int *__ptidptr __asm__("r7") = parent_tidptr;
1588 register void *__newtls __asm__("r8") = newtls;
1589 register int *__ctidptr __asm__("r9") = child_tidptr;
1590
1591 __asm__ __volatile__(
1592 /* fn and arg are saved across the syscall */
1593 "mr 28, %5\n\t"
1594 "mr 27, %8\n\t"
1595
1596 /* syscall
1597 r0 == __NR_clone
1598 r3 == flags
1599 r4 == child_stack
1600 r5 == parent_tidptr
1601 r6 == newtls
1602 r7 == child_tidptr */
1603 "mr 3, %7\n\t"
1604 "mr 5, %9\n\t"
1605 "mr 6, %10\n\t"
1606 "mr 7, %11\n\t"
1607 "li 0, %3\n\t"
1608 "sc\n\t"
1609
1610 /* Test if syscall was successful */
1611 "cmpdi cr1, 3, 0\n\t"
1612 "crandc cr1*4+eq, cr1*4+eq, cr0*4+so\n\t"
1613 "bne- cr1, 1f\n\t"
1614
1615 /* Set up stack frame */
1616 "li 29, 0\n\t"
1617 "stdu 29, -8(1)\n\t"
1618 "stdu 1, -%12(1)\n\t"
1619 /* Do the function call */
1620 "std 2, %13(1)\n\t"
1621#if SANITIZER_PPC64V1
1622 "ld 0, 0(28)\n\t"
1623 "ld 2, 8(28)\n\t"
1624 "mtctr 0\n\t"
1625#elif SANITIZER_PPC64V2
1626 "mr 12, 28\n\t"
1627 "mtctr 12\n\t"
1628#else
1629# error "Unsupported PPC64 ABI"
1630#endif
1631 "mr 3, 27\n\t"
1632 "bctrl\n\t"
1633 "ld 2, %13(1)\n\t"
1634
1635 /* Call _exit(r3) */
1636 "li 0, %4\n\t"
1637 "sc\n\t"
1638
1639 /* Return to parent */
1640 "1:\n\t"
1641 "mr %0, 3\n\t"
1642 : "=r" (res)
1643 : "0" (-1),
1644 "i" (EINVAL),
1645 "i" (__NR_clone),
1646 "i" (__NR_exit),
1647 "r" (__fn),
1648 "r" (__cstack),
1649 "r" (__flags),
1650 "r" (__arg),
1651 "r" (__ptidptr),
1652 "r" (__newtls),
1653 "r" (__ctidptr),
1654 "i" (FRAME_SIZE),
1655 "i" (FRAME_TOC_SAVE_OFFSET)
1656 : "cr0", "cr1", "memory", "ctr", "r0", "r27", "r28", "r29");
1610 register void *__cstack __asm__("r4") = child_stack;
1611 register int __flags __asm__("r5") = flags;
1612 register void *__arg __asm__("r6") = arg;
1613 register int *__ptidptr __asm__("r7") = parent_tidptr;
1614 register void *__newtls __asm__("r8") = newtls;
1615 register int *__ctidptr __asm__("r9") = child_tidptr;
1616
1617 __asm__ __volatile__(
1618 /* fn and arg are saved across the syscall */
1619 "mr 28, %5\n\t"
1620 "mr 27, %8\n\t"
1621
1622 /* syscall
1623 r0 == __NR_clone
1624 r3 == flags
1625 r4 == child_stack
1626 r5 == parent_tidptr
1627 r6 == newtls
1628 r7 == child_tidptr */
1629 "mr 3, %7\n\t"
1630 "mr 5, %9\n\t"
1631 "mr 6, %10\n\t"
1632 "mr 7, %11\n\t"
1633 "li 0, %3\n\t"
1634 "sc\n\t"
1635
1636 /* Test if syscall was successful */
1637 "cmpdi cr1, 3, 0\n\t"
1638 "crandc cr1*4+eq, cr1*4+eq, cr0*4+so\n\t"
1639 "bne- cr1, 1f\n\t"
1640
1641 /* Set up stack frame */
1642 "li 29, 0\n\t"
1643 "stdu 29, -8(1)\n\t"
1644 "stdu 1, -%12(1)\n\t"
1645 /* Do the function call */
1646 "std 2, %13(1)\n\t"
1647# if SANITIZER_PPC64V1
1648 "ld 0, 0(28)\n\t"
1649 "ld 2, 8(28)\n\t"
1650 "mtctr 0\n\t"
1651# elif SANITIZER_PPC64V2
1652 "mr 12, 28\n\t"
1653 "mtctr 12\n\t"
1654# else
1655# error "Unsupported PPC64 ABI"
1656# endif
1657 "mr 3, 27\n\t"
1658 "bctrl\n\t"
1659 "ld 2, %13(1)\n\t"
1660
1661 /* Call _exit(r3) */
1662 "li 0, %4\n\t"
1663 "sc\n\t"
1664
1665 /* Return to parent */
1666 "1:\n\t"
1667 "mr %0, 3\n\t"
1668 : "=r"(res)
1669 : "0"(-1), "i"(EINVAL), "i"(__NR_clone), "i"(__NR_exit), "r"(__fn),
1670 "r"(__cstack), "r"(__flags), "r"(__arg), "r"(__ptidptr), "r"(__newtls),
1671 "r"(__ctidptr), "i"(FRAME_SIZE), "i"(FRAME_TOC_SAVE_OFFSET)
1672 : "cr0", "cr1", "memory", "ctr", "r0", "r27", "r28", "r29");
16571673 return res;
16581674}
1659#elif defined(__i386__)
1675# elif defined(__i386__)
16601676uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
16611677 int *parent_tidptr, void *newtls, int *child_tidptr) {
16621678 int res;
......@@ -1669,59 +1685,56 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
16691685 ((unsigned int *)child_stack)[2] = (uptr)fn;
16701686 ((unsigned int *)child_stack)[3] = (uptr)arg;
16711687 __asm__ __volatile__(
1672 /* %eax = syscall(%eax = SYSCALL(clone),
1673 * %ebx = flags,
1674 * %ecx = child_stack,
1675 * %edx = parent_tidptr,
1676 * %esi = new_tls,
1677 * %edi = child_tidptr)
1678 */
1679
1680 /* Obtain flags */
1681 "movl (%%ecx), %%ebx\n"
1682 /* Do the system call */
1683 "pushl %%ebx\n"
1684 "pushl %%esi\n"
1685 "pushl %%edi\n"
1686 /* Remember the flag value. */
1687 "movl %%ebx, (%%ecx)\n"
1688 "int $0x80\n"
1689 "popl %%edi\n"
1690 "popl %%esi\n"
1691 "popl %%ebx\n"
1692
1693 /* if (%eax != 0)
1694 * return;
1695 */
1696
1697 "test %%eax,%%eax\n"
1698 "jnz 1f\n"
1699
1700 /* terminate the stack frame */
1701 "xorl %%ebp,%%ebp\n"
1702 /* Call FN. */
1703 "call *%%ebx\n"
1704#ifdef PIC
1705 "call here\n"
1706 "here:\n"
1707 "popl %%ebx\n"
1708 "addl $_GLOBAL_OFFSET_TABLE_+[.-here], %%ebx\n"
1709#endif
1710 /* Call exit */
1711 "movl %%eax, %%ebx\n"
1712 "movl %2, %%eax\n"
1713 "int $0x80\n"
1714 "1:\n"
1715 : "=a" (res)
1716 : "a"(SYSCALL(clone)), "i"(SYSCALL(exit)),
1717 "c"(child_stack),
1718 "d"(parent_tidptr),
1719 "S"(newtls),
1720 "D"(child_tidptr)
1721 : "memory");
1688 /* %eax = syscall(%eax = SYSCALL(clone),
1689 * %ebx = flags,
1690 * %ecx = child_stack,
1691 * %edx = parent_tidptr,
1692 * %esi = new_tls,
1693 * %edi = child_tidptr)
1694 */
1695
1696 /* Obtain flags */
1697 "movl (%%ecx), %%ebx\n"
1698 /* Do the system call */
1699 "pushl %%ebx\n"
1700 "pushl %%esi\n"
1701 "pushl %%edi\n"
1702 /* Remember the flag value. */
1703 "movl %%ebx, (%%ecx)\n"
1704 "int $0x80\n"
1705 "popl %%edi\n"
1706 "popl %%esi\n"
1707 "popl %%ebx\n"
1708
1709 /* if (%eax != 0)
1710 * return;
1711 */
1712
1713 "test %%eax,%%eax\n"
1714 "jnz 1f\n"
1715
1716 /* terminate the stack frame */
1717 "xorl %%ebp,%%ebp\n"
1718 /* Call FN. */
1719 "call *%%ebx\n"
1720# ifdef PIC
1721 "call here\n"
1722 "here:\n"
1723 "popl %%ebx\n"
1724 "addl $_GLOBAL_OFFSET_TABLE_+[.-here], %%ebx\n"
1725# endif
1726 /* Call exit */
1727 "movl %%eax, %%ebx\n"
1728 "movl %2, %%eax\n"
1729 "int $0x80\n"
1730 "1:\n"
1731 : "=a"(res)
1732 : "a"(SYSCALL(clone)), "i"(SYSCALL(exit)), "c"(child_stack),
1733 "d"(parent_tidptr), "S"(newtls), "D"(child_tidptr)
1734 : "memory");
17221735 return res;
17231736}
1724#elif defined(__arm__)
1737# elif defined(__arm__)
17251738uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
17261739 int *parent_tidptr, void *newtls, int *child_tidptr) {
17271740 unsigned int res;
......@@ -1737,70 +1750,68 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
17371750 register int *r4 __asm__("r4") = child_tidptr;
17381751 register int r7 __asm__("r7") = __NR_clone;
17391752
1740#if __ARM_ARCH > 4 || defined (__ARM_ARCH_4T__)
1741# define ARCH_HAS_BX
1742#endif
1743#if __ARM_ARCH > 4
1744# define ARCH_HAS_BLX
1745#endif
1753# if __ARM_ARCH > 4 || defined(__ARM_ARCH_4T__)
1754# define ARCH_HAS_BX
1755# endif
1756# if __ARM_ARCH > 4
1757# define ARCH_HAS_BLX
1758# endif
17461759
1747#ifdef ARCH_HAS_BX
1748# ifdef ARCH_HAS_BLX
1749# define BLX(R) "blx " #R "\n"
1750# else
1751# define BLX(R) "mov lr, pc; bx " #R "\n"
1752# endif
1753#else
1754# define BLX(R) "mov lr, pc; mov pc," #R "\n"
1755#endif
1760# ifdef ARCH_HAS_BX
1761# ifdef ARCH_HAS_BLX
1762# define BLX(R) "blx " #R "\n"
1763# else
1764# define BLX(R) "mov lr, pc; bx " #R "\n"
1765# endif
1766# else
1767# define BLX(R) "mov lr, pc; mov pc," #R "\n"
1768# endif
17561769
17571770 __asm__ __volatile__(
1758 /* %r0 = syscall(%r7 = SYSCALL(clone),
1759 * %r0 = flags,
1760 * %r1 = child_stack,
1761 * %r2 = parent_tidptr,
1762 * %r3 = new_tls,
1763 * %r4 = child_tidptr)
1764 */
1765
1766 /* Do the system call */
1767 "swi 0x0\n"
1768
1769 /* if (%r0 != 0)
1770 * return %r0;
1771 */
1772 "cmp r0, #0\n"
1773 "bne 1f\n"
1774
1775 /* In the child, now. Call "fn(arg)". */
1776 "ldr r0, [sp, #4]\n"
1777 "ldr ip, [sp], #8\n"
1778 BLX(ip)
1779 /* Call _exit(%r0). */
1780 "mov r7, %7\n"
1781 "swi 0x0\n"
1782 "1:\n"
1783 "mov %0, r0\n"
1784 : "=r"(res)
1785 : "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r7),
1786 "i"(__NR_exit)
1787 : "memory");
1771 /* %r0 = syscall(%r7 = SYSCALL(clone),
1772 * %r0 = flags,
1773 * %r1 = child_stack,
1774 * %r2 = parent_tidptr,
1775 * %r3 = new_tls,
1776 * %r4 = child_tidptr)
1777 */
1778
1779 /* Do the system call */
1780 "swi 0x0\n"
1781
1782 /* if (%r0 != 0)
1783 * return %r0;
1784 */
1785 "cmp r0, #0\n"
1786 "bne 1f\n"
1787
1788 /* In the child, now. Call "fn(arg)". */
1789 "ldr r0, [sp, #4]\n"
1790 "ldr ip, [sp], #8\n" BLX(ip)
1791 /* Call _exit(%r0). */
1792 "mov r7, %7\n"
1793 "swi 0x0\n"
1794 "1:\n"
1795 "mov %0, r0\n"
1796 : "=r"(res)
1797 : "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r7), "i"(__NR_exit)
1798 : "memory");
17881799 return res;
17891800}
1790#endif
1791#endif // SANITIZER_LINUX
1801# endif
1802# endif // SANITIZER_LINUX
17921803
1793#if SANITIZER_LINUX
1804# if SANITIZER_LINUX
17941805int internal_uname(struct utsname *buf) {
17951806 return internal_syscall(SYSCALL(uname), buf);
17961807}
1797#endif
1808# endif
17981809
1799#if SANITIZER_ANDROID
1800#if __ANDROID_API__ < 21
1810# if SANITIZER_ANDROID
1811# if __ANDROID_API__ < 21
18011812extern "C" __attribute__((weak)) int dl_iterate_phdr(
18021813 int (*)(struct dl_phdr_info *, size_t, void *), void *);
1803#endif
1814# endif
18041815
18051816static int dl_iterate_phdr_test_cb(struct dl_phdr_info *info, size_t size,
18061817 void *data) {
......@@ -1817,40 +1828,41 @@ static int dl_iterate_phdr_test_cb(struct dl_phdr_info *info, size_t size,
18171828static atomic_uint32_t android_api_level;
18181829
18191830static AndroidApiLevel AndroidDetectApiLevelStatic() {
1820#if __ANDROID_API__ <= 19
1831# if __ANDROID_API__ <= 19
18211832 return ANDROID_KITKAT;
1822#elif __ANDROID_API__ <= 22
1833# elif __ANDROID_API__ <= 22
18231834 return ANDROID_LOLLIPOP_MR1;
1824#else
1835# else
18251836 return ANDROID_POST_LOLLIPOP;
1826#endif
1837# endif
18271838}
18281839
18291840static AndroidApiLevel AndroidDetectApiLevel() {
18301841 if (!&dl_iterate_phdr)
1831 return ANDROID_KITKAT; // K or lower
1842 return ANDROID_KITKAT; // K or lower
18321843 bool base_name_seen = false;
18331844 dl_iterate_phdr(dl_iterate_phdr_test_cb, &base_name_seen);
18341845 if (base_name_seen)
1835 return ANDROID_LOLLIPOP_MR1; // L MR1
1846 return ANDROID_LOLLIPOP_MR1; // L MR1
18361847 return ANDROID_POST_LOLLIPOP; // post-L
18371848 // Plain L (API level 21) is completely broken wrt ASan and not very
18381849 // interesting to detect.
18391850}
18401851
1841extern "C" __attribute__((weak)) void* _DYNAMIC;
1852extern "C" __attribute__((weak)) void *_DYNAMIC;
18421853
18431854AndroidApiLevel AndroidGetApiLevel() {
18441855 AndroidApiLevel level =
18451856 (AndroidApiLevel)atomic_load(&android_api_level, memory_order_relaxed);
1846 if (level) return level;
1857 if (level)
1858 return level;
18471859 level = &_DYNAMIC == nullptr ? AndroidDetectApiLevelStatic()
18481860 : AndroidDetectApiLevel();
18491861 atomic_store(&android_api_level, level, memory_order_relaxed);
18501862 return level;
18511863}
18521864
1853#endif
1865# endif
18541866
18551867static HandleSignalMode GetHandleSignalModeImpl(int signum) {
18561868 switch (signum) {
......@@ -1877,28 +1889,28 @@ HandleSignalMode GetHandleSignalMode(int signum) {
18771889 return result;
18781890}
18791891
1880#if !SANITIZER_GO
1892# if !SANITIZER_GO
18811893void *internal_start_thread(void *(*func)(void *arg), void *arg) {
1882 if (&real_pthread_create == 0)
1894 if (&internal_pthread_create == 0)
18831895 return nullptr;
18841896 // Start the thread with signals blocked, otherwise it can steal user signals.
18851897 ScopedBlockSignals block(nullptr);
18861898 void *th;
1887 real_pthread_create(&th, nullptr, func, arg);
1899 internal_pthread_create(&th, nullptr, func, arg);
18881900 return th;
18891901}
18901902
18911903void internal_join_thread(void *th) {
1892 if (&real_pthread_join)
1893 real_pthread_join(th, nullptr);
1904 if (&internal_pthread_join)
1905 internal_pthread_join(th, nullptr);
18941906}
1895#else
1907# else
18961908void *internal_start_thread(void *(*func)(void *), void *arg) { return 0; }
18971909
18981910void internal_join_thread(void *th) {}
1899#endif
1911# endif
19001912
1901#if SANITIZER_LINUX && defined(__aarch64__)
1913# if SANITIZER_LINUX && defined(__aarch64__)
19021914// Android headers in the older NDK releases miss this definition.
19031915struct __sanitizer_esr_context {
19041916 struct _aarch64_ctx head;
......@@ -1910,7 +1922,8 @@ static bool Aarch64GetESR(ucontext_t *ucontext, u64 *esr) {
19101922 u8 *aux = reinterpret_cast<u8 *>(ucontext->uc_mcontext.__reserved);
19111923 while (true) {
19121924 _aarch64_ctx *ctx = (_aarch64_ctx *)aux;
1913 if (ctx->size == 0) break;
1925 if (ctx->size == 0)
1926 break;
19141927 if (ctx->magic == kEsrMagic) {
19151928 *esr = ((__sanitizer_esr_context *)ctx)->esr;
19161929 return true;
......@@ -1919,31 +1932,29 @@ static bool Aarch64GetESR(ucontext_t *ucontext, u64 *esr) {
19191932 }
19201933 return false;
19211934}
1922#elif SANITIZER_FREEBSD && defined(__aarch64__)
1935# elif SANITIZER_FREEBSD && defined(__aarch64__)
19231936// FreeBSD doesn't provide ESR in the ucontext.
1924static bool Aarch64GetESR(ucontext_t *ucontext, u64 *esr) {
1925 return false;
1926}
1927#endif
1937static bool Aarch64GetESR(ucontext_t *ucontext, u64 *esr) { return false; }
1938# endif
19281939
19291940using Context = ucontext_t;
19301941
19311942SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
19321943 Context *ucontext = (Context *)context;
1933#if defined(__x86_64__) || defined(__i386__)
1944# if defined(__x86_64__) || defined(__i386__)
19341945 static const uptr PF_WRITE = 1U << 1;
1935#if SANITIZER_FREEBSD
1946# if SANITIZER_FREEBSD
19361947 uptr err = ucontext->uc_mcontext.mc_err;
1937#elif SANITIZER_NETBSD
1948# elif SANITIZER_NETBSD
19381949 uptr err = ucontext->uc_mcontext.__gregs[_REG_ERR];
1939#elif SANITIZER_SOLARIS && defined(__i386__)
1950# elif SANITIZER_SOLARIS && defined(__i386__)
19401951 const int Err = 13;
19411952 uptr err = ucontext->uc_mcontext.gregs[Err];
1942#else
1953# else
19431954 uptr err = ucontext->uc_mcontext.gregs[REG_ERR];
1944#endif // SANITIZER_FREEBSD
1955# endif // SANITIZER_FREEBSD
19451956 return err & PF_WRITE ? Write : Read;
1946#elif defined(__mips__)
1957# elif defined(__mips__)
19471958 uint32_t *exception_source;
19481959 uint32_t faulty_instruction;
19491960 uint32_t op_code;
......@@ -1959,12 +1970,12 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
19591970 case 0x29: // sh
19601971 case 0x2b: // sw
19611972 case 0x3f: // sd
1962#if __mips_isa_rev < 6
1973# if __mips_isa_rev < 6
19631974 case 0x2c: // sdl
19641975 case 0x2d: // sdr
19651976 case 0x2a: // swl
19661977 case 0x2e: // swr
1967#endif
1978# endif
19681979 return SignalContext::Write;
19691980
19701981 case 0x20: // lb
......@@ -1974,14 +1985,14 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
19741985 case 0x23: // lw
19751986 case 0x27: // lwu
19761987 case 0x37: // ld
1977#if __mips_isa_rev < 6
1988# if __mips_isa_rev < 6
19781989 case 0x1a: // ldl
19791990 case 0x1b: // ldr
19801991 case 0x22: // lwl
19811992 case 0x26: // lwr
1982#endif
1993# endif
19831994 return SignalContext::Read;
1984#if __mips_isa_rev == 6
1995# if __mips_isa_rev == 6
19851996 case 0x3b: // pcrel
19861997 op_code = (faulty_instruction >> 19) & 0x3;
19871998 switch (op_code) {
......@@ -1989,50 +2000,51 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
19892000 case 0x2: // lwupc
19902001 return SignalContext::Read;
19912002 }
1992#endif
2003# endif
19932004 }
19942005 return SignalContext::Unknown;
1995#elif defined(__arm__)
2006# elif defined(__arm__)
19962007 static const uptr FSR_WRITE = 1U << 11;
19972008 uptr fsr = ucontext->uc_mcontext.error_code;
19982009 return fsr & FSR_WRITE ? Write : Read;
1999#elif defined(__aarch64__)
2010# elif defined(__aarch64__)
20002011 static const u64 ESR_ELx_WNR = 1U << 6;
20012012 u64 esr;
2002 if (!Aarch64GetESR(ucontext, &esr)) return Unknown;
2013 if (!Aarch64GetESR(ucontext, &esr))
2014 return Unknown;
20032015 return esr & ESR_ELx_WNR ? Write : Read;
2004#elif defined(__loongarch__)
2016# elif defined(__loongarch__)
20052017 u32 flags = ucontext->uc_mcontext.__flags;
20062018 if (flags & SC_ADDRERR_RD)
20072019 return SignalContext::Read;
20082020 if (flags & SC_ADDRERR_WR)
20092021 return SignalContext::Write;
20102022 return SignalContext::Unknown;
2011#elif defined(__sparc__)
2023# elif defined(__sparc__)
20122024 // Decode the instruction to determine the access type.
20132025 // From OpenSolaris $SRC/uts/sun4/os/trap.c (get_accesstype).
2014#if SANITIZER_SOLARIS
2026# if SANITIZER_SOLARIS
20152027 uptr pc = ucontext->uc_mcontext.gregs[REG_PC];
2016#else
2028# else
20172029 // Historical BSDism here.
20182030 struct sigcontext *scontext = (struct sigcontext *)context;
2019#if defined(__arch64__)
2031# if defined(__arch64__)
20202032 uptr pc = scontext->sigc_regs.tpc;
2021#else
2033# else
20222034 uptr pc = scontext->si_regs.pc;
2023#endif
2024#endif
2035# endif
2036# endif
20252037 u32 instr = *(u32 *)pc;
2026 return (instr >> 21) & 1 ? Write: Read;
2027#elif defined(__riscv)
2028#if SANITIZER_FREEBSD
2038 return (instr >> 21) & 1 ? Write : Read;
2039# elif defined(__riscv)
2040# if SANITIZER_FREEBSD
20292041 unsigned long pc = ucontext->uc_mcontext.mc_gpregs.gp_sepc;
2030#else
2042# else
20312043 unsigned long pc = ucontext->uc_mcontext.__gregs[REG_PC];
2032#endif
2044# endif
20332045 unsigned faulty_instruction = *(uint16_t *)pc;
20342046
2035#if defined(__riscv_compressed)
2047# if defined(__riscv_compressed)
20362048 if ((faulty_instruction & 0x3) != 0x3) { // it's a compressed instruction
20372049 // set op_bits to the instruction bits [1, 0, 15, 14, 13]
20382050 unsigned op_bits =
......@@ -2040,38 +2052,38 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
20402052 unsigned rd = faulty_instruction & 0xF80; // bits 7-11, inclusive
20412053 switch (op_bits) {
20422054 case 0b10'010: // c.lwsp (rd != x0)
2043#if __riscv_xlen == 64
2055# if __riscv_xlen == 64
20442056 case 0b10'011: // c.ldsp (rd != x0)
2045#endif
2057# endif
20462058 return rd ? SignalContext::Read : SignalContext::Unknown;
20472059 case 0b00'010: // c.lw
2048#if __riscv_flen >= 32 && __riscv_xlen == 32
2060# if __riscv_flen >= 32 && __riscv_xlen == 32
20492061 case 0b10'011: // c.flwsp
2050#endif
2051#if __riscv_flen >= 32 || __riscv_xlen == 64
2062# endif
2063# if __riscv_flen >= 32 || __riscv_xlen == 64
20522064 case 0b00'011: // c.flw / c.ld
2053#endif
2054#if __riscv_flen == 64
2065# endif
2066# if __riscv_flen == 64
20552067 case 0b00'001: // c.fld
20562068 case 0b10'001: // c.fldsp
2057#endif
2069# endif
20582070 return SignalContext::Read;
20592071 case 0b00'110: // c.sw
20602072 case 0b10'110: // c.swsp
2061#if __riscv_flen >= 32 || __riscv_xlen == 64
2073# if __riscv_flen >= 32 || __riscv_xlen == 64
20622074 case 0b00'111: // c.fsw / c.sd
20632075 case 0b10'111: // c.fswsp / c.sdsp
2064#endif
2065#if __riscv_flen == 64
2076# endif
2077# if __riscv_flen == 64
20662078 case 0b00'101: // c.fsd
20672079 case 0b10'101: // c.fsdsp
2068#endif
2080# endif
20692081 return SignalContext::Write;
20702082 default:
20712083 return SignalContext::Unknown;
20722084 }
20732085 }
2074#endif
2086# endif
20752087
20762088 unsigned opcode = faulty_instruction & 0x7f; // lower 7 bits
20772089 unsigned funct3 = (faulty_instruction >> 12) & 0x7; // bits 12-14, inclusive
......@@ -2081,9 +2093,9 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
20812093 case 0b000: // lb
20822094 case 0b001: // lh
20832095 case 0b010: // lw
2084#if __riscv_xlen == 64
2096# if __riscv_xlen == 64
20852097 case 0b011: // ld
2086#endif
2098# endif
20872099 case 0b100: // lbu
20882100 case 0b101: // lhu
20892101 return SignalContext::Read;
......@@ -2095,20 +2107,20 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
20952107 case 0b000: // sb
20962108 case 0b001: // sh
20972109 case 0b010: // sw
2098#if __riscv_xlen == 64
2110# if __riscv_xlen == 64
20992111 case 0b011: // sd
2100#endif
2112# endif
21012113 return SignalContext::Write;
21022114 default:
21032115 return SignalContext::Unknown;
21042116 }
2105#if __riscv_flen >= 32
2117# if __riscv_flen >= 32
21062118 case 0b0000111: // floating-point loads
21072119 switch (funct3) {
21082120 case 0b010: // flw
2109#if __riscv_flen == 64
2121# if __riscv_flen == 64
21102122 case 0b011: // fld
2111#endif
2123# endif
21122124 return SignalContext::Read;
21132125 default:
21142126 return SignalContext::Unknown;
......@@ -2116,21 +2128,21 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
21162128 case 0b0100111: // floating-point stores
21172129 switch (funct3) {
21182130 case 0b010: // fsw
2119#if __riscv_flen == 64
2131# if __riscv_flen == 64
21202132 case 0b011: // fsd
2121#endif
2133# endif
21222134 return SignalContext::Write;
21232135 default:
21242136 return SignalContext::Unknown;
21252137 }
2126#endif
2138# endif
21272139 default:
21282140 return SignalContext::Unknown;
21292141 }
2130#else
2142# else
21312143 (void)ucontext;
21322144 return Unknown; // FIXME: Implement.
2133#endif
2145# endif
21342146}
21352147
21362148bool SignalContext::IsTrueFaultingAddress() const {
......@@ -2139,129 +2151,288 @@ bool SignalContext::IsTrueFaultingAddress() const {
21392151 return si->si_signo == SIGSEGV && si->si_code != 128;
21402152}
21412153
2154UNUSED
2155static const char *RegNumToRegName(int reg) {
2156 switch (reg) {
2157# if SANITIZER_LINUX
2158# if defined(__x86_64__)
2159 case REG_RAX:
2160 return "rax";
2161 case REG_RBX:
2162 return "rbx";
2163 case REG_RCX:
2164 return "rcx";
2165 case REG_RDX:
2166 return "rdx";
2167 case REG_RDI:
2168 return "rdi";
2169 case REG_RSI:
2170 return "rsi";
2171 case REG_RBP:
2172 return "rbp";
2173 case REG_RSP:
2174 return "rsp";
2175 case REG_R8:
2176 return "r8";
2177 case REG_R9:
2178 return "r9";
2179 case REG_R10:
2180 return "r10";
2181 case REG_R11:
2182 return "r11";
2183 case REG_R12:
2184 return "r12";
2185 case REG_R13:
2186 return "r13";
2187 case REG_R14:
2188 return "r14";
2189 case REG_R15:
2190 return "r15";
2191# elif defined(__i386__)
2192 case REG_EAX:
2193 return "eax";
2194 case REG_EBX:
2195 return "ebx";
2196 case REG_ECX:
2197 return "ecx";
2198 case REG_EDX:
2199 return "edx";
2200 case REG_EDI:
2201 return "edi";
2202 case REG_ESI:
2203 return "esi";
2204 case REG_EBP:
2205 return "ebp";
2206 case REG_ESP:
2207 return "esp";
2208# endif
2209# endif
2210 default:
2211 return NULL;
2212 }
2213 return NULL;
2214}
2215
2216# if SANITIZER_LINUX
2217UNUSED
2218static void DumpSingleReg(ucontext_t *ctx, int RegNum) {
2219 const char *RegName = RegNumToRegName(RegNum);
2220# if defined(__x86_64__)
2221 Printf("%s%s = 0x%016llx ", internal_strlen(RegName) == 2 ? " " : "",
2222 RegName, ctx->uc_mcontext.gregs[RegNum]);
2223# elif defined(__i386__)
2224 Printf("%s = 0x%08x ", RegName, ctx->uc_mcontext.gregs[RegNum]);
2225# else
2226 (void)RegName;
2227# endif
2228}
2229# endif
2230
21422231void SignalContext::DumpAllRegisters(void *context) {
2143 // FIXME: Implement this.
2232 ucontext_t *ucontext = (ucontext_t *)context;
2233# if SANITIZER_LINUX
2234# if defined(__x86_64__)
2235 Report("Register values:\n");
2236 DumpSingleReg(ucontext, REG_RAX);
2237 DumpSingleReg(ucontext, REG_RBX);
2238 DumpSingleReg(ucontext, REG_RCX);
2239 DumpSingleReg(ucontext, REG_RDX);
2240 Printf("\n");
2241 DumpSingleReg(ucontext, REG_RDI);
2242 DumpSingleReg(ucontext, REG_RSI);
2243 DumpSingleReg(ucontext, REG_RBP);
2244 DumpSingleReg(ucontext, REG_RSP);
2245 Printf("\n");
2246 DumpSingleReg(ucontext, REG_R8);
2247 DumpSingleReg(ucontext, REG_R9);
2248 DumpSingleReg(ucontext, REG_R10);
2249 DumpSingleReg(ucontext, REG_R11);
2250 Printf("\n");
2251 DumpSingleReg(ucontext, REG_R12);
2252 DumpSingleReg(ucontext, REG_R13);
2253 DumpSingleReg(ucontext, REG_R14);
2254 DumpSingleReg(ucontext, REG_R15);
2255 Printf("\n");
2256# elif defined(__i386__)
2257 // Duplication of this report print is caused by partial support
2258 // of register values dumping. In case of unsupported yet architecture let's
2259 // avoid printing 'Register values:' without actual values in the following
2260 // output.
2261 Report("Register values:\n");
2262 DumpSingleReg(ucontext, REG_EAX);
2263 DumpSingleReg(ucontext, REG_EBX);
2264 DumpSingleReg(ucontext, REG_ECX);
2265 DumpSingleReg(ucontext, REG_EDX);
2266 Printf("\n");
2267 DumpSingleReg(ucontext, REG_EDI);
2268 DumpSingleReg(ucontext, REG_ESI);
2269 DumpSingleReg(ucontext, REG_EBP);
2270 DumpSingleReg(ucontext, REG_ESP);
2271 Printf("\n");
2272# else
2273 (void)ucontext;
2274# endif
2275# elif SANITIZER_FREEBSD
2276# if defined(__x86_64__)
2277 Report("Register values:\n");
2278 Printf("rax = 0x%016lx ", ucontext->uc_mcontext.mc_rax);
2279 Printf("rbx = 0x%016lx ", ucontext->uc_mcontext.mc_rbx);
2280 Printf("rcx = 0x%016lx ", ucontext->uc_mcontext.mc_rcx);
2281 Printf("rdx = 0x%016lx ", ucontext->uc_mcontext.mc_rdx);
2282 Printf("\n");
2283 Printf("rdi = 0x%016lx ", ucontext->uc_mcontext.mc_rdi);
2284 Printf("rsi = 0x%016lx ", ucontext->uc_mcontext.mc_rsi);
2285 Printf("rbp = 0x%016lx ", ucontext->uc_mcontext.mc_rbp);
2286 Printf("rsp = 0x%016lx ", ucontext->uc_mcontext.mc_rsp);
2287 Printf("\n");
2288 Printf(" r8 = 0x%016lx ", ucontext->uc_mcontext.mc_r8);
2289 Printf(" r9 = 0x%016lx ", ucontext->uc_mcontext.mc_r9);
2290 Printf("r10 = 0x%016lx ", ucontext->uc_mcontext.mc_r10);
2291 Printf("r11 = 0x%016lx ", ucontext->uc_mcontext.mc_r11);
2292 Printf("\n");
2293 Printf("r12 = 0x%016lx ", ucontext->uc_mcontext.mc_r12);
2294 Printf("r13 = 0x%016lx ", ucontext->uc_mcontext.mc_r13);
2295 Printf("r14 = 0x%016lx ", ucontext->uc_mcontext.mc_r14);
2296 Printf("r15 = 0x%016lx ", ucontext->uc_mcontext.mc_r15);
2297 Printf("\n");
2298# elif defined(__i386__)
2299 Report("Register values:\n");
2300 Printf("eax = 0x%08x ", ucontext->uc_mcontext.mc_eax);
2301 Printf("ebx = 0x%08x ", ucontext->uc_mcontext.mc_ebx);
2302 Printf("ecx = 0x%08x ", ucontext->uc_mcontext.mc_ecx);
2303 Printf("edx = 0x%08x ", ucontext->uc_mcontext.mc_edx);
2304 Printf("\n");
2305 Printf("edi = 0x%08x ", ucontext->uc_mcontext.mc_edi);
2306 Printf("esi = 0x%08x ", ucontext->uc_mcontext.mc_esi);
2307 Printf("ebp = 0x%08x ", ucontext->uc_mcontext.mc_ebp);
2308 Printf("esp = 0x%08x ", ucontext->uc_mcontext.mc_esp);
2309 Printf("\n");
2310# else
2311 (void)ucontext;
2312# endif
2313# endif
2314 // FIXME: Implement this for other OSes and architectures.
21442315}
21452316
21462317static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
2147#if SANITIZER_NETBSD
2318# if SANITIZER_NETBSD
21482319 // This covers all NetBSD architectures
21492320 ucontext_t *ucontext = (ucontext_t *)context;
21502321 *pc = _UC_MACHINE_PC(ucontext);
21512322 *bp = _UC_MACHINE_FP(ucontext);
21522323 *sp = _UC_MACHINE_SP(ucontext);
2153#elif defined(__arm__)
2154 ucontext_t *ucontext = (ucontext_t*)context;
2324# elif defined(__arm__)
2325 ucontext_t *ucontext = (ucontext_t *)context;
21552326 *pc = ucontext->uc_mcontext.arm_pc;
21562327 *bp = ucontext->uc_mcontext.arm_fp;
21572328 *sp = ucontext->uc_mcontext.arm_sp;
2158#elif defined(__aarch64__)
2159# if SANITIZER_FREEBSD
2160 ucontext_t *ucontext = (ucontext_t*)context;
2329# elif defined(__aarch64__)
2330# if SANITIZER_FREEBSD
2331 ucontext_t *ucontext = (ucontext_t *)context;
21612332 *pc = ucontext->uc_mcontext.mc_gpregs.gp_elr;
21622333 *bp = ucontext->uc_mcontext.mc_gpregs.gp_x[29];
21632334 *sp = ucontext->uc_mcontext.mc_gpregs.gp_sp;
2164# else
2165 ucontext_t *ucontext = (ucontext_t*)context;
2335# else
2336 ucontext_t *ucontext = (ucontext_t *)context;
21662337 *pc = ucontext->uc_mcontext.pc;
21672338 *bp = ucontext->uc_mcontext.regs[29];
21682339 *sp = ucontext->uc_mcontext.sp;
2169# endif
2170#elif defined(__hppa__)
2171 ucontext_t *ucontext = (ucontext_t*)context;
2340# endif
2341# elif defined(__hppa__)
2342 ucontext_t *ucontext = (ucontext_t *)context;
21722343 *pc = ucontext->uc_mcontext.sc_iaoq[0];
21732344 /* GCC uses %r3 whenever a frame pointer is needed. */
21742345 *bp = ucontext->uc_mcontext.sc_gr[3];
21752346 *sp = ucontext->uc_mcontext.sc_gr[30];
2176#elif defined(__x86_64__)
2177# if SANITIZER_FREEBSD
2178 ucontext_t *ucontext = (ucontext_t*)context;
2347# elif defined(__x86_64__)
2348# if SANITIZER_FREEBSD
2349 ucontext_t *ucontext = (ucontext_t *)context;
21792350 *pc = ucontext->uc_mcontext.mc_rip;
21802351 *bp = ucontext->uc_mcontext.mc_rbp;
21812352 *sp = ucontext->uc_mcontext.mc_rsp;
2182# else
2183 ucontext_t *ucontext = (ucontext_t*)context;
2353# else
2354 ucontext_t *ucontext = (ucontext_t *)context;
21842355 *pc = ucontext->uc_mcontext.gregs[REG_RIP];
21852356 *bp = ucontext->uc_mcontext.gregs[REG_RBP];
21862357 *sp = ucontext->uc_mcontext.gregs[REG_RSP];
2187# endif
2188#elif defined(__i386__)
2189# if SANITIZER_FREEBSD
2190 ucontext_t *ucontext = (ucontext_t*)context;
2358# endif
2359# elif defined(__i386__)
2360# if SANITIZER_FREEBSD
2361 ucontext_t *ucontext = (ucontext_t *)context;
21912362 *pc = ucontext->uc_mcontext.mc_eip;
21922363 *bp = ucontext->uc_mcontext.mc_ebp;
21932364 *sp = ucontext->uc_mcontext.mc_esp;
2194# else
2195 ucontext_t *ucontext = (ucontext_t*)context;
2196# if SANITIZER_SOLARIS
2365# else
2366 ucontext_t *ucontext = (ucontext_t *)context;
2367# if SANITIZER_SOLARIS
21972368 /* Use the numeric values: the symbolic ones are undefined by llvm
21982369 include/llvm/Support/Solaris.h. */
2199# ifndef REG_EIP
2200# define REG_EIP 14 // REG_PC
2201# endif
2202# ifndef REG_EBP
2203# define REG_EBP 6 // REG_FP
2204# endif
2205# ifndef REG_UESP
2206# define REG_UESP 17 // REG_SP
2207# endif
2208# endif
2370# ifndef REG_EIP
2371# define REG_EIP 14 // REG_PC
2372# endif
2373# ifndef REG_EBP
2374# define REG_EBP 6 // REG_FP
2375# endif
2376# ifndef REG_UESP
2377# define REG_UESP 17 // REG_SP
2378# endif
2379# endif
22092380 *pc = ucontext->uc_mcontext.gregs[REG_EIP];
22102381 *bp = ucontext->uc_mcontext.gregs[REG_EBP];
22112382 *sp = ucontext->uc_mcontext.gregs[REG_UESP];
2212# endif
2213#elif defined(__powerpc__) || defined(__powerpc64__)
2383# endif
2384# elif defined(__powerpc__) || defined(__powerpc64__)
22142385# if SANITIZER_FREEBSD
22152386 ucontext_t *ucontext = (ucontext_t *)context;
22162387 *pc = ucontext->uc_mcontext.mc_srr0;
22172388 *sp = ucontext->uc_mcontext.mc_frame[1];
22182389 *bp = ucontext->uc_mcontext.mc_frame[31];
22192390# else
2220 ucontext_t *ucontext = (ucontext_t*)context;
2391 ucontext_t *ucontext = (ucontext_t *)context;
22212392 *pc = ucontext->uc_mcontext.regs->nip;
22222393 *sp = ucontext->uc_mcontext.regs->gpr[PT_R1];
22232394 // The powerpc{,64}-linux ABIs do not specify r31 as the frame
22242395 // pointer, but GCC always uses r31 when we need a frame pointer.
22252396 *bp = ucontext->uc_mcontext.regs->gpr[PT_R31];
22262397# endif
2227#elif defined(__sparc__)
2228#if defined(__arch64__) || defined(__sparcv9)
2229#define STACK_BIAS 2047
2230#else
2231#define STACK_BIAS 0
2232# endif
2233# if SANITIZER_SOLARIS
2398# elif defined(__sparc__)
2399# if defined(__arch64__) || defined(__sparcv9)
2400# define STACK_BIAS 2047
2401# else
2402# define STACK_BIAS 0
2403# endif
2404# if SANITIZER_SOLARIS
22342405 ucontext_t *ucontext = (ucontext_t *)context;
22352406 *pc = ucontext->uc_mcontext.gregs[REG_PC];
22362407 *sp = ucontext->uc_mcontext.gregs[REG_O6] + STACK_BIAS;
2237#else
2408# else
22382409 // Historical BSDism here.
22392410 struct sigcontext *scontext = (struct sigcontext *)context;
2240#if defined(__arch64__)
2411# if defined(__arch64__)
22412412 *pc = scontext->sigc_regs.tpc;
22422413 *sp = scontext->sigc_regs.u_regs[14] + STACK_BIAS;
2243#else
2414# else
22442415 *pc = scontext->si_regs.pc;
22452416 *sp = scontext->si_regs.u_regs[14];
2246#endif
2247# endif
2417# endif
2418# endif
22482419 *bp = (uptr)((uhwptr *)*sp)[14] + STACK_BIAS;
2249#elif defined(__mips__)
2250 ucontext_t *ucontext = (ucontext_t*)context;
2420# elif defined(__mips__)
2421 ucontext_t *ucontext = (ucontext_t *)context;
22512422 *pc = ucontext->uc_mcontext.pc;
22522423 *bp = ucontext->uc_mcontext.gregs[30];
22532424 *sp = ucontext->uc_mcontext.gregs[29];
2254#elif defined(__s390__)
2255 ucontext_t *ucontext = (ucontext_t*)context;
2256# if defined(__s390x__)
2425# elif defined(__s390__)
2426 ucontext_t *ucontext = (ucontext_t *)context;
2427# if defined(__s390x__)
22572428 *pc = ucontext->uc_mcontext.psw.addr;
2258# else
2429# else
22592430 *pc = ucontext->uc_mcontext.psw.addr & 0x7fffffff;
2260# endif
2431# endif
22612432 *bp = ucontext->uc_mcontext.gregs[11];
22622433 *sp = ucontext->uc_mcontext.gregs[15];
2263#elif defined(__riscv)
2264 ucontext_t *ucontext = (ucontext_t*)context;
2434# elif defined(__riscv)
2435 ucontext_t *ucontext = (ucontext_t *)context;
22652436# if SANITIZER_FREEBSD
22662437 *pc = ucontext->uc_mcontext.mc_gpregs.gp_sepc;
22672438 *bp = ucontext->uc_mcontext.mc_gpregs.gp_s[0];
......@@ -2293,7 +2464,7 @@ void InitializePlatformEarly() {
22932464}
22942465
22952466void CheckASLR() {
2296#if SANITIZER_NETBSD
2467# if SANITIZER_NETBSD
22972468 int mib[3];
22982469 int paxflags;
22992470 uptr len = sizeof(paxflags);
......@@ -2308,12 +2479,13 @@ void CheckASLR() {
23082479 }
23092480
23102481 if (UNLIKELY(paxflags & CTL_PROC_PAXFLAGS_ASLR)) {
2311 Printf("This sanitizer is not compatible with enabled ASLR.\n"
2312 "To disable ASLR, please run \"paxctl +a %s\" and try again.\n",
2313 GetArgv()[0]);
2482 Printf(
2483 "This sanitizer is not compatible with enabled ASLR.\n"
2484 "To disable ASLR, please run \"paxctl +a %s\" and try again.\n",
2485 GetArgv()[0]);
23142486 Die();
23152487 }
2316#elif SANITIZER_FREEBSD
2488# elif SANITIZER_FREEBSD
23172489 int aslr_status;
23182490 int r = internal_procctl(P_PID, 0, PROC_ASLR_STATUS, &aslr_status);
23192491 if (UNLIKELY(r == -1)) {
......@@ -2323,9 +2495,13 @@ void CheckASLR() {
23232495 return;
23242496 }
23252497 if ((aslr_status & PROC_ASLR_ACTIVE) != 0) {
2326 Printf("This sanitizer is not compatible with enabled ASLR "
2327 "and binaries compiled with PIE\n");
2328 Die();
2498 VReport(1,
2499 "This sanitizer is not compatible with enabled ASLR "
2500 "and binaries compiled with PIE\n"
2501 "ASLR will be disabled and the program re-executed.\n");
2502 int aslr_ctl = PROC_ASLR_FORCE_DISABLE;
2503 CHECK_NE(internal_procctl(P_PID, 0, PROC_ASLR_CTL, &aslr_ctl), -1);
2504 ReExec();
23292505 }
23302506# elif SANITIZER_PPC64V2
23312507 // Disable ASLR for Linux PPC64LE.
......@@ -2345,7 +2521,7 @@ void CheckASLR() {
23452521}
23462522
23472523void CheckMPROTECT() {
2348#if SANITIZER_NETBSD
2524# if SANITIZER_NETBSD
23492525 int mib[3];
23502526 int paxflags;
23512527 uptr len = sizeof(paxflags);
......@@ -2363,13 +2539,13 @@ void CheckMPROTECT() {
23632539 Printf("This sanitizer is not compatible with enabled MPROTECT\n");
23642540 Die();
23652541 }
2366#else
2542# else
23672543 // Do nothing
2368#endif
2544# endif
23692545}
23702546
23712547void CheckNoDeepBind(const char *filename, int flag) {
2372#ifdef RTLD_DEEPBIND
2548# ifdef RTLD_DEEPBIND
23732549 if (flag & RTLD_DEEPBIND) {
23742550 Report(
23752551 "You are trying to dlopen a %s shared library with RTLD_DEEPBIND flag"
......@@ -2380,7 +2556,7 @@ void CheckNoDeepBind(const char *filename, int flag) {
23802556 filename, filename);
23812557 Die();
23822558 }
2383#endif
2559# endif
23842560}
23852561
23862562uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,
......@@ -2393,16 +2569,16 @@ uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,
23932569bool GetRandom(void *buffer, uptr length, bool blocking) {
23942570 if (!buffer || !length || length > 256)
23952571 return false;
2396#if SANITIZER_USE_GETENTROPY
2572# if SANITIZER_USE_GETENTROPY
23972573 uptr rnd = getentropy(buffer, length);
23982574 int rverrno = 0;
23992575 if (internal_iserror(rnd, &rverrno) && rverrno == EFAULT)
24002576 return false;
24012577 else if (rnd == 0)
24022578 return true;
2403#endif // SANITIZER_USE_GETENTROPY
2579# endif // SANITIZER_USE_GETENTROPY
24042580
2405#if SANITIZER_USE_GETRANDOM
2581# if SANITIZER_USE_GETRANDOM
24062582 static atomic_uint8_t skip_getrandom_syscall;
24072583 if (!atomic_load_relaxed(&skip_getrandom_syscall)) {
24082584 // Up to 256 bytes, getrandom will not be interrupted.
......@@ -2414,7 +2590,7 @@ bool GetRandom(void *buffer, uptr length, bool blocking) {
24142590 else if (res == length)
24152591 return true;
24162592 }
2417#endif // SANITIZER_USE_GETRANDOM
2593# endif // SANITIZER_USE_GETRANDOM
24182594 // Up to 256 bytes, a read off /dev/urandom will not be interrupted.
24192595 // blocking is moot here, O_NONBLOCK has no effect when opening /dev/urandom.
24202596 uptr fd = internal_open("/dev/urandom", O_RDONLY);
......@@ -2427,6 +2603,6 @@ bool GetRandom(void *buffer, uptr length, bool blocking) {
24272603 return true;
24282604}
24292605
2430} // namespace __sanitizer
2606} // namespace __sanitizer
24312607
24322608#endif
lib/tsan/sanitizer_common/sanitizer_linux.h+69-45
......@@ -13,15 +13,15 @@
1313#define SANITIZER_LINUX_H
1414
1515#include "sanitizer_platform.h"
16#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
16#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
1717 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_posix.h"
23#include "sanitizer_platform_limits_solaris.h"
24#include "sanitizer_posix.h"
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_posix.h"
23# include "sanitizer_platform_limits_solaris.h"
24# include "sanitizer_posix.h"
2525
2626struct link_map; // Opaque type returned by dlopen().
2727struct utsname;
......@@ -46,9 +46,9 @@ void ReadProcMaps(ProcSelfMapsBuff *proc_maps);
4646
4747// Syscall wrappers.
4848uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count);
49uptr internal_sigaltstack(const void* ss, void* oss);
49uptr internal_sigaltstack(const void *ss, void *oss);
5050uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set,
51 __sanitizer_sigset_t *oldset);
51 __sanitizer_sigset_t *oldset);
5252
5353void SetSigProcMask(__sanitizer_sigset_t *set, __sanitizer_sigset_t *oldset);
5454void BlockSignals(__sanitizer_sigset_t *oldset = nullptr);
......@@ -65,10 +65,10 @@ struct ScopedBlockSignals {
6565
6666# if SANITIZER_GLIBC
6767uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp);
68#endif
68# endif
6969
7070// Linux-only syscalls.
71#if SANITIZER_LINUX
71# if SANITIZER_LINUX
7272uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5);
7373# if defined(__x86_64__)
7474uptr internal_arch_prctl(int option, uptr arg2);
......@@ -83,15 +83,15 @@ void internal_sigdelset(__sanitizer_sigset_t *set, int signum);
8383 defined(__arm__) || SANITIZER_RISCV64 || SANITIZER_LOONGARCH64
8484uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
8585 int *parent_tidptr, void *newtls, int *child_tidptr);
86#endif
86# endif
8787int internal_uname(struct utsname *buf);
88#elif SANITIZER_FREEBSD
88# elif SANITIZER_FREEBSD
8989uptr internal_procctl(int type, int id, int cmd, void *data);
9090void internal_sigdelset(__sanitizer_sigset_t *set, int signum);
91#elif SANITIZER_NETBSD
91# elif SANITIZER_NETBSD
9292void internal_sigdelset(__sanitizer_sigset_t *set, int signum);
9393uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg);
94#endif // SANITIZER_LINUX
94# endif // SANITIZER_LINUX
9595
9696// This class reads thread IDs from /proc/<pid>/task using only syscalls.
9797class ThreadLister {
......@@ -135,36 +135,60 @@ inline void ReleaseMemoryPagesToOSAndZeroFill(uptr beg, uptr end) {
135135 ReleaseMemoryPagesToOS(beg, end);
136136}
137137
138#if SANITIZER_ANDROID
139
140#if defined(__aarch64__)
141# define __get_tls() \
142 ({ void** __v; __asm__("mrs %0, tpidr_el0" : "=r"(__v)); __v; })
143#elif defined(__arm__)
144# define __get_tls() \
145 ({ void** __v; __asm__("mrc p15, 0, %0, c13, c0, 3" : "=r"(__v)); __v; })
146#elif defined(__mips__)
138# if SANITIZER_ANDROID
139
140# if defined(__aarch64__)
141# define __get_tls() \
142 ({ \
143 void **__v; \
144 __asm__("mrs %0, tpidr_el0" : "=r"(__v)); \
145 __v; \
146 })
147# elif defined(__arm__)
148# define __get_tls() \
149 ({ \
150 void **__v; \
151 __asm__("mrc p15, 0, %0, c13, c0, 3" : "=r"(__v)); \
152 __v; \
153 })
154# elif defined(__mips__)
147155// On mips32r1, this goes via a kernel illegal instruction trap that's
148156// optimized for v1.
149# define __get_tls() \
150 ({ register void** __v asm("v1"); \
151 __asm__(".set push\n" \
152 ".set mips32r2\n" \
153 "rdhwr %0,$29\n" \
154 ".set pop\n" : "=r"(__v)); \
155 __v; })
156#elif defined (__riscv)
157# define __get_tls() \
158 ({ void** __v; __asm__("mv %0, tp" : "=r"(__v)); __v; })
159#elif defined(__i386__)
160# define __get_tls() \
161 ({ void** __v; __asm__("movl %%gs:0, %0" : "=r"(__v)); __v; })
162#elif defined(__x86_64__)
163# define __get_tls() \
164 ({ void** __v; __asm__("mov %%fs:0, %0" : "=r"(__v)); __v; })
165#else
166#error "Unsupported architecture."
167#endif
157# define __get_tls() \
158 ({ \
159 register void **__v asm("v1"); \
160 __asm__( \
161 ".set push\n" \
162 ".set mips32r2\n" \
163 "rdhwr %0,$29\n" \
164 ".set pop\n" \
165 : "=r"(__v)); \
166 __v; \
167 })
168# elif defined(__riscv)
169# define __get_tls() \
170 ({ \
171 void **__v; \
172 __asm__("mv %0, tp" : "=r"(__v)); \
173 __v; \
174 })
175# elif defined(__i386__)
176# define __get_tls() \
177 ({ \
178 void **__v; \
179 __asm__("movl %%gs:0, %0" : "=r"(__v)); \
180 __v; \
181 })
182# elif defined(__x86_64__)
183# define __get_tls() \
184 ({ \
185 void **__v; \
186 __asm__("mov %%fs:0, %0" : "=r"(__v)); \
187 __v; \
188 })
189# else
190# error "Unsupported architecture."
191# endif
168192
169193// The Android Bionic team has allocated a TLS slot for sanitizers starting
170194// with Q, given that Android currently doesn't support ELF TLS. It is used to
......@@ -175,7 +199,7 @@ ALWAYS_INLINE uptr *get_android_tls_ptr() {
175199 return reinterpret_cast<uptr *>(&__get_tls()[TLS_SLOT_SANITIZER]);
176200}
177201
178#endif // SANITIZER_ANDROID
202# endif // SANITIZER_ANDROID
179203
180204} // namespace __sanitizer
181205
lib/tsan/sanitizer_common/sanitizer_linux_libcdep.cpp+252-231
......@@ -16,89 +16,101 @@
1616#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
1717 SANITIZER_SOLARIS
1818
19#include "sanitizer_allocator_internal.h"
20#include "sanitizer_atomic.h"
21#include "sanitizer_common.h"
22#include "sanitizer_file.h"
23#include "sanitizer_flags.h"
24#include "sanitizer_freebsd.h"
25#include "sanitizer_getauxval.h"
26#include "sanitizer_glibc_version.h"
27#include "sanitizer_linux.h"
28#include "sanitizer_placement_new.h"
29#include "sanitizer_procmaps.h"
30#include "sanitizer_solaris.h"
31
32#if SANITIZER_NETBSD
33#define _RTLD_SOURCE // for __lwp_gettcb_fast() / __lwp_getprivate_fast()
34#endif
19# include "sanitizer_allocator_internal.h"
20# include "sanitizer_atomic.h"
21# include "sanitizer_common.h"
22# include "sanitizer_file.h"
23# include "sanitizer_flags.h"
24# include "sanitizer_getauxval.h"
25# include "sanitizer_glibc_version.h"
26# include "sanitizer_linux.h"
27# include "sanitizer_placement_new.h"
28# include "sanitizer_procmaps.h"
29# include "sanitizer_solaris.h"
30
31# if SANITIZER_NETBSD
32# define _RTLD_SOURCE // for __lwp_gettcb_fast() / __lwp_getprivate_fast()
33# endif
3534
36#include <dlfcn.h> // for dlsym()
37#include <link.h>
38#include <pthread.h>
39#include <signal.h>
40#include <sys/mman.h>
41#include <sys/resource.h>
42#include <syslog.h>
35# include <dlfcn.h> // for dlsym()
36# include <link.h>
37# include <pthread.h>
38# include <signal.h>
39# include <sys/mman.h>
40# include <sys/resource.h>
41# include <syslog.h>
4342
44#if !defined(ElfW)
45#define ElfW(type) Elf_##type
46#endif
43# if !defined(ElfW)
44# define ElfW(type) Elf_##type
45# endif
4746
48#if SANITIZER_FREEBSD
49#include <pthread_np.h>
50#include <osreldate.h>
51#include <sys/sysctl.h>
52#define pthread_getattr_np pthread_attr_get_np
47# if SANITIZER_FREEBSD
48# include <pthread_np.h>
49# include <sys/auxv.h>
50# include <sys/sysctl.h>
51# define pthread_getattr_np pthread_attr_get_np
5352// The MAP_NORESERVE define has been removed in FreeBSD 11.x, and even before
5453// that, it was never implemented. So just define it to zero.
55#undef MAP_NORESERVE
56#define MAP_NORESERVE 0
57#endif
54# undef MAP_NORESERVE
55# define MAP_NORESERVE 0
56extern const Elf_Auxinfo *__elf_aux_vector;
57extern "C" int __sys_sigaction(int signum, const struct sigaction *act,
58 struct sigaction *oldact);
59# endif
5860
59#if SANITIZER_NETBSD
60#include <sys/sysctl.h>
61#include <sys/tls.h>
62#include <lwp.h>
63#endif
61# if SANITIZER_NETBSD
62# include <lwp.h>
63# include <sys/sysctl.h>
64# include <sys/tls.h>
65# endif
6466
65#if SANITIZER_SOLARIS
66#include <stddef.h>
67#include <stdlib.h>
68#include <thread.h>
69#endif
67# if SANITIZER_SOLARIS
68# include <stddef.h>
69# include <stdlib.h>
70# include <thread.h>
71# endif
7072
71#if SANITIZER_ANDROID
72#include <android/api-level.h>
73#if !defined(CPU_COUNT) && !defined(__aarch64__)
74#include <dirent.h>
75#include <fcntl.h>
73# if SANITIZER_ANDROID
74# include <android/api-level.h>
75# if !defined(CPU_COUNT) && !defined(__aarch64__)
76# include <dirent.h>
77# include <fcntl.h>
7678struct __sanitizer::linux_dirent {
77 long d_ino;
78 off_t d_off;
79 long d_ino;
80 off_t d_off;
7981 unsigned short d_reclen;
80 char d_name[];
82 char d_name[];
8183};
82#endif
83#endif
84# endif
85# endif
8486
85#if !SANITIZER_ANDROID
86#include <elf.h>
87#include <unistd.h>
88#endif
87# if !SANITIZER_ANDROID
88# include <elf.h>
89# include <unistd.h>
90# endif
8991
9092namespace __sanitizer {
9193
92SANITIZER_WEAK_ATTRIBUTE int
93real_sigaction(int signum, const void *act, void *oldact);
94SANITIZER_WEAK_ATTRIBUTE int real_sigaction(int signum, const void *act,
95 void *oldact);
9496
9597int internal_sigaction(int signum, const void *act, void *oldact) {
96#if !SANITIZER_GO
98# if SANITIZER_FREEBSD
99 // On FreeBSD, call the sigaction syscall directly (part of libsys in FreeBSD
100 // 15) since the libc version goes via a global interposing table. Due to
101 // library initialization order the table can be relocated after the call to
102 // InitializeDeadlySignals() which then crashes when dereferencing the
103 // uninitialized pointer in libc.
104 return __sys_sigaction(signum, (const struct sigaction *)act,
105 (struct sigaction *)oldact);
106# else
107# if !SANITIZER_GO
97108 if (&real_sigaction)
98109 return real_sigaction(signum, act, oldact);
99#endif
110# endif
100111 return sigaction(signum, (const struct sigaction *)act,
101112 (struct sigaction *)oldact);
113# endif
102114}
103115
104116void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
......@@ -111,7 +123,7 @@ void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
111123 CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0);
112124
113125 // Find the mapping that contains a stack variable.
114 MemoryMappingLayout proc_maps(/*cache_enabled*/true);
126 MemoryMappingLayout proc_maps(/*cache_enabled*/ true);
115127 if (proc_maps.Error()) {
116128 *stack_top = *stack_bottom = 0;
117129 return;
......@@ -119,7 +131,8 @@ void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
119131 MemoryMappedSegment segment;
120132 uptr prev_end = 0;
121133 while (proc_maps.Next(&segment)) {
122 if ((uptr)&rl < segment.end) break;
134 if ((uptr)&rl < segment.end)
135 break;
123136 prev_end = segment.end;
124137 }
125138 CHECK((uptr)&rl >= segment.start && (uptr)&rl < segment.end);
......@@ -127,7 +140,8 @@ void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
127140 // Get stacksize from rlimit, but clip it so that it does not overlap
128141 // with other mappings.
129142 uptr stacksize = rl.rlim_cur;
130 if (stacksize > segment.end - prev_end) stacksize = segment.end - prev_end;
143 if (stacksize > segment.end - prev_end)
144 stacksize = segment.end - prev_end;
131145 // When running with unlimited stack size, we still want to set some limit.
132146 // The unlimited stack size is caused by 'ulimit -s unlimited'.
133147 // Also, for some reason, GNU make spawns subprocesses with unlimited stack.
......@@ -135,43 +149,56 @@ void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
135149 stacksize = kMaxThreadStackSize;
136150 *stack_top = segment.end;
137151 *stack_bottom = segment.end - stacksize;
152
153 uptr maxAddr = GetMaxUserVirtualAddress();
154 // Edge case: the stack mapping on some systems may be off-by-one e.g.,
155 // fffffffdf000-1000000000000 rw-p 00000000 00:00 0 [stack]
156 // instead of:
157 // fffffffdf000- ffffffffffff
158 // The out-of-range stack_top can result in an invalid shadow address
159 // calculation, since those usually assume the parameters are in range.
160 if (*stack_top == maxAddr + 1)
161 *stack_top = maxAddr;
162 else
163 CHECK_LE(*stack_top, maxAddr);
164
138165 return;
139166 }
140167 uptr stacksize = 0;
141168 void *stackaddr = nullptr;
142#if SANITIZER_SOLARIS
169# if SANITIZER_SOLARIS
143170 stack_t ss;
144171 CHECK_EQ(thr_stksegment(&ss), 0);
145172 stacksize = ss.ss_size;
146173 stackaddr = (char *)ss.ss_sp - stacksize;
147#else // !SANITIZER_SOLARIS
174# else // !SANITIZER_SOLARIS
148175 pthread_attr_t attr;
149176 pthread_attr_init(&attr);
150177 CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0);
151178 internal_pthread_attr_getstack(&attr, &stackaddr, &stacksize);
152179 pthread_attr_destroy(&attr);
153#endif // SANITIZER_SOLARIS
180# endif // SANITIZER_SOLARIS
154181
155182 *stack_top = (uptr)stackaddr + stacksize;
156183 *stack_bottom = (uptr)stackaddr;
157184}
158185
159#if !SANITIZER_GO
186# if !SANITIZER_GO
160187bool SetEnv(const char *name, const char *value) {
161188 void *f = dlsym(RTLD_NEXT, "setenv");
162189 if (!f)
163190 return false;
164 typedef int(*setenv_ft)(const char *name, const char *value, int overwrite);
191 typedef int (*setenv_ft)(const char *name, const char *value, int overwrite);
165192 setenv_ft setenv_f;
166193 CHECK_EQ(sizeof(setenv_f), sizeof(f));
167194 internal_memcpy(&setenv_f, &f, sizeof(f));
168195 return setenv_f(name, value, 1) == 0;
169196}
170#endif
197# endif
171198
172199__attribute__((unused)) static bool GetLibcVersion(int *major, int *minor,
173200 int *patch) {
174#ifdef _CS_GNU_LIBC_VERSION
201# ifdef _CS_GNU_LIBC_VERSION
175202 char buf[64];
176203 uptr len = confstr(_CS_GNU_LIBC_VERSION, buf, sizeof(buf));
177204 if (len >= sizeof(buf))
......@@ -185,9 +212,9 @@ __attribute__((unused)) static bool GetLibcVersion(int *major, int *minor,
185212 *minor = (*p == '.') ? internal_simple_strtoll(p + 1, &p, 10) : 0;
186213 *patch = (*p == '.') ? internal_simple_strtoll(p + 1, &p, 10) : 0;
187214 return true;
188#else
215# else
189216 return false;
190#endif
217# endif
191218}
192219
193220// True if we can use dlpi_tls_data. glibc before 2.25 may leave NULL (BZ
......@@ -198,42 +225,42 @@ __attribute__((unused)) static bool GetLibcVersion(int *major, int *minor,
198225// https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=254774
199226__attribute__((unused)) static int g_use_dlpi_tls_data;
200227
201#if SANITIZER_GLIBC && !SANITIZER_GO
228# if SANITIZER_GLIBC && !SANITIZER_GO
202229__attribute__((unused)) static size_t g_tls_size;
203230void InitTlsSize() {
204231 int major, minor, patch;
205232 g_use_dlpi_tls_data =
206233 GetLibcVersion(&major, &minor, &patch) && major == 2 && minor >= 25;
207234
208#if defined(__aarch64__) || defined(__x86_64__) || defined(__powerpc64__) || \
209 defined(__loongarch__)
235# if defined(__aarch64__) || defined(__x86_64__) || \
236 defined(__powerpc64__) || defined(__loongarch__)
210237 void *get_tls_static_info = dlsym(RTLD_NEXT, "_dl_get_tls_static_info");
211238 size_t tls_align;
212239 ((void (*)(size_t *, size_t *))get_tls_static_info)(&g_tls_size, &tls_align);
213#endif
240# endif
214241}
215#else
216void InitTlsSize() { }
217#endif // SANITIZER_GLIBC && !SANITIZER_GO
242# else
243void InitTlsSize() {}
244# endif // SANITIZER_GLIBC && !SANITIZER_GO
218245
219246// On glibc x86_64, ThreadDescriptorSize() needs to be precise due to the usage
220247// of g_tls_size. On other targets, ThreadDescriptorSize() is only used by lsan
221248// to get the pointer to thread-specific data keys in the thread control block.
222#if (SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_SOLARIS) && \
223 !SANITIZER_ANDROID && !SANITIZER_GO
249# if (SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_SOLARIS) && \
250 !SANITIZER_ANDROID && !SANITIZER_GO
224251// sizeof(struct pthread) from glibc.
225252static atomic_uintptr_t thread_descriptor_size;
226253
227254static uptr ThreadDescriptorSizeFallback() {
228255 uptr val = 0;
229#if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
256# if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
230257 int major;
231258 int minor;
232259 int patch;
233260 if (GetLibcVersion(&major, &minor, &patch) && major == 2) {
234261 /* sizeof(struct pthread) values from various glibc versions. */
235262 if (SANITIZER_X32)
236 val = 1728; // Assume only one particular version for x32.
263 val = 1728; // Assume only one particular version for x32.
237264 // For ARM sizeof(struct pthread) changed in Glibc 2.23.
238265 else if (SANITIZER_ARM)
239266 val = minor <= 22 ? 1120 : 1216;
......@@ -256,19 +283,19 @@ static uptr ThreadDescriptorSizeFallback() {
256283 else // minor == 32
257284 val = FIRST_32_SECOND_64(1344, 2496);
258285 }
259#elif defined(__s390__) || defined(__sparc__)
286# elif defined(__s390__) || defined(__sparc__)
260287 // The size of a prefix of TCB including pthread::{specific_1stblock,specific}
261288 // suffices. Just return offsetof(struct pthread, specific_used), which hasn't
262289 // changed since 2007-05. Technically this applies to i386/x86_64 as well but
263290 // we call _dl_get_tls_static_info and need the precise size of struct
264291 // pthread.
265292 return FIRST_32_SECOND_64(524, 1552);
266#elif defined(__mips__)
293# elif defined(__mips__)
267294 // TODO(sagarthakur): add more values as per different glibc versions.
268295 val = FIRST_32_SECOND_64(1152, 1776);
269#elif SANITIZER_LOONGARCH64
270 val = 1856; // from glibc 2.36
271#elif SANITIZER_RISCV64
296# elif SANITIZER_LOONGARCH64
297 val = 1856; // from glibc 2.36
298# elif SANITIZER_RISCV64
272299 int major;
273300 int minor;
274301 int patch;
......@@ -283,12 +310,12 @@ static uptr ThreadDescriptorSizeFallback() {
283310 val = 1936; // tested against glibc 2.32
284311 }
285312
286#elif defined(__aarch64__)
313# elif defined(__aarch64__)
287314 // The sizeof (struct pthread) is the same from GLIBC 2.17 to 2.22.
288315 val = 1776;
289#elif defined(__powerpc64__)
290 val = 1776; // from glibc.ppc64le 2.20-8.fc21
291#endif
316# elif defined(__powerpc64__)
317 val = 1776; // from glibc.ppc64le 2.20-8.fc21
318# endif
292319 return val;
293320}
294321
......@@ -307,26 +334,26 @@ uptr ThreadDescriptorSize() {
307334 return val;
308335}
309336
310#if defined(__mips__) || defined(__powerpc64__) || SANITIZER_RISCV64 || \
311 SANITIZER_LOONGARCH64
337# if defined(__mips__) || defined(__powerpc64__) || SANITIZER_RISCV64 || \
338 SANITIZER_LOONGARCH64
312339// TlsPreTcbSize includes size of struct pthread_descr and size of tcb
313340// head structure. It lies before the static tls blocks.
314341static uptr TlsPreTcbSize() {
315#if defined(__mips__)
316 const uptr kTcbHead = 16; // sizeof (tcbhead_t)
317#elif defined(__powerpc64__)
318 const uptr kTcbHead = 88; // sizeof (tcbhead_t)
319#elif SANITIZER_RISCV64
342# if defined(__mips__)
320343 const uptr kTcbHead = 16; // sizeof (tcbhead_t)
321#elif SANITIZER_LOONGARCH64
344# elif defined(__powerpc64__)
345 const uptr kTcbHead = 88; // sizeof (tcbhead_t)
346# elif SANITIZER_RISCV64
322347 const uptr kTcbHead = 16; // sizeof (tcbhead_t)
323#endif
348# elif SANITIZER_LOONGARCH64
349 const uptr kTcbHead = 16; // sizeof (tcbhead_t)
350# endif
324351 const uptr kTlsAlign = 16;
325352 const uptr kTlsPreTcbSize =
326353 RoundUpTo(ThreadDescriptorSize() + kTcbHead, kTlsAlign);
327354 return kTlsPreTcbSize;
328355}
329#endif
356# endif
330357
331358namespace {
332359struct TlsBlock {
......@@ -336,7 +363,7 @@ struct TlsBlock {
336363};
337364} // namespace
338365
339#ifdef __s390__
366# ifdef __s390__
340367extern "C" uptr __tls_get_offset(void *arg);
341368
342369static uptr TlsGetOffset(uptr ti_module, uptr ti_offset) {
......@@ -354,16 +381,16 @@ static uptr TlsGetOffset(uptr ti_module, uptr ti_offset) {
354381 : "memory", "cc", "0", "1", "3", "4", "5", "14");
355382 return r2;
356383}
357#else
384# else
358385extern "C" void *__tls_get_addr(size_t *);
359#endif
386# endif
360387
361388static size_t main_tls_modid;
362389
363390static int CollectStaticTlsBlocks(struct dl_phdr_info *info, size_t size,
364391 void *data) {
365392 size_t tls_modid;
366#if SANITIZER_SOLARIS
393# if SANITIZER_SOLARIS
367394 // dlpi_tls_modid is only available since Solaris 11.4 SRU 10. Use
368395 // dlinfo(RTLD_DI_LINKMAP) instead which works on all of Solaris 11.3,
369396 // 11.4, and Illumos. The tlsmodid of the executable was changed to 1 in
......@@ -376,27 +403,26 @@ static int CollectStaticTlsBlocks(struct dl_phdr_info *info, size_t size,
376403 Rt_map *map;
377404 dlinfo(RTLD_SELF, RTLD_DI_LINKMAP, &map);
378405 tls_modid = map->rt_tlsmodid;
379#else
406# else
380407 main_tls_modid = 1;
381408 tls_modid = info->dlpi_tls_modid;
382#endif
409# endif
383410
384411 if (tls_modid < main_tls_modid)
385412 return 0;
386413 uptr begin;
387#if !SANITIZER_SOLARIS
414# if !SANITIZER_SOLARIS
388415 begin = (uptr)info->dlpi_tls_data;
389#endif
416# endif
390417 if (!g_use_dlpi_tls_data) {
391418 // Call __tls_get_addr as a fallback. This forces TLS allocation on glibc
392419 // and FreeBSD.
393#ifdef __s390__
394 begin = (uptr)__builtin_thread_pointer() +
395 TlsGetOffset(tls_modid, 0);
396#else
420# ifdef __s390__
421 begin = (uptr)__builtin_thread_pointer() + TlsGetOffset(tls_modid, 0);
422# else
397423 size_t mod_and_off[2] = {tls_modid, 0};
398424 begin = (uptr)__tls_get_addr(mod_and_off);
399#endif
425# endif
400426 }
401427 for (unsigned i = 0; i != info->dlpi_phnum; ++i)
402428 if (info->dlpi_phdr[i].p_type == PT_TLS) {
......@@ -439,23 +465,21 @@ __attribute__((unused)) static void GetStaticTlsBoundary(uptr *addr, uptr *size,
439465 *addr = ranges[l].begin;
440466 *size = ranges[r - 1].end - ranges[l].begin;
441467}
442#endif // (x86_64 || i386 || mips || ...) && (SANITIZER_FREEBSD ||
443 // SANITIZER_LINUX) && !SANITIZER_ANDROID && !SANITIZER_GO
468# endif // (x86_64 || i386 || mips || ...) && (SANITIZER_FREEBSD ||
469 // SANITIZER_LINUX) && !SANITIZER_ANDROID && !SANITIZER_GO
444470
445#if SANITIZER_NETBSD
446static struct tls_tcb * ThreadSelfTlsTcb() {
471# if SANITIZER_NETBSD
472static struct tls_tcb *ThreadSelfTlsTcb() {
447473 struct tls_tcb *tcb = nullptr;
448#ifdef __HAVE___LWP_GETTCB_FAST
474# ifdef __HAVE___LWP_GETTCB_FAST
449475 tcb = (struct tls_tcb *)__lwp_gettcb_fast();
450#elif defined(__HAVE___LWP_GETPRIVATE_FAST)
476# elif defined(__HAVE___LWP_GETPRIVATE_FAST)
451477 tcb = (struct tls_tcb *)__lwp_getprivate_fast();
452#endif
478# endif
453479 return tcb;
454480}
455481
456uptr ThreadSelf() {
457 return (uptr)ThreadSelfTlsTcb()->tcb_pthread;
458}
482uptr ThreadSelf() { return (uptr)ThreadSelfTlsTcb()->tcb_pthread; }
459483
460484int GetSizeFromHdr(struct dl_phdr_info *info, size_t size, void *data) {
461485 const Elf_Phdr *hdr = info->dlpi_phdr;
......@@ -463,23 +487,23 @@ int GetSizeFromHdr(struct dl_phdr_info *info, size_t size, void *data) {
463487
464488 for (; hdr != last_hdr; ++hdr) {
465489 if (hdr->p_type == PT_TLS && info->dlpi_tls_modid == 1) {
466 *(uptr*)data = hdr->p_memsz;
490 *(uptr *)data = hdr->p_memsz;
467491 break;
468492 }
469493 }
470494 return 0;
471495}
472#endif // SANITIZER_NETBSD
496# endif // SANITIZER_NETBSD
473497
474#if SANITIZER_ANDROID
498# if SANITIZER_ANDROID
475499// Bionic provides this API since S.
476500extern "C" SANITIZER_WEAK_ATTRIBUTE void __libc_get_static_tls_bounds(void **,
477501 void **);
478#endif
502# endif
479503
480#if !SANITIZER_GO
504# if !SANITIZER_GO
481505static void GetTls(uptr *addr, uptr *size) {
482#if SANITIZER_ANDROID
506# if SANITIZER_ANDROID
483507 if (&__libc_get_static_tls_bounds) {
484508 void *start_addr;
485509 void *end_addr;
......@@ -491,48 +515,48 @@ static void GetTls(uptr *addr, uptr *size) {
491515 *addr = 0;
492516 *size = 0;
493517 }
494#elif SANITIZER_GLIBC && defined(__x86_64__)
518# elif SANITIZER_GLIBC && defined(__x86_64__)
495519 // For aarch64 and x86-64, use an O(1) approach which requires relatively
496520 // precise ThreadDescriptorSize. g_tls_size was initialized in InitTlsSize.
497# if SANITIZER_X32
521# if SANITIZER_X32
498522 asm("mov %%fs:8,%0" : "=r"(*addr));
499# else
523# else
500524 asm("mov %%fs:16,%0" : "=r"(*addr));
501# endif
525# endif
502526 *size = g_tls_size;
503527 *addr -= *size;
504528 *addr += ThreadDescriptorSize();
505#elif SANITIZER_GLIBC && defined(__aarch64__)
529# elif SANITIZER_GLIBC && defined(__aarch64__)
506530 *addr = reinterpret_cast<uptr>(__builtin_thread_pointer()) -
507531 ThreadDescriptorSize();
508532 *size = g_tls_size + ThreadDescriptorSize();
509#elif SANITIZER_GLIBC && defined(__loongarch__)
510# ifdef __clang__
533# elif SANITIZER_GLIBC && defined(__loongarch__)
534# ifdef __clang__
511535 *addr = reinterpret_cast<uptr>(__builtin_thread_pointer()) -
512536 ThreadDescriptorSize();
513# else
537# else
514538 asm("or %0,$tp,$zero" : "=r"(*addr));
515539 *addr -= ThreadDescriptorSize();
516# endif
540# endif
517541 *size = g_tls_size + ThreadDescriptorSize();
518#elif SANITIZER_GLIBC && defined(__powerpc64__)
542# elif SANITIZER_GLIBC && defined(__powerpc64__)
519543 // Workaround for glibc<2.25(?). 2.27 is known to not need this.
520544 uptr tp;
521545 asm("addi %0,13,-0x7000" : "=r"(tp));
522546 const uptr pre_tcb_size = TlsPreTcbSize();
523547 *addr = tp - pre_tcb_size;
524548 *size = g_tls_size + pre_tcb_size;
525#elif SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_SOLARIS
549# elif SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_SOLARIS
526550 uptr align;
527551 GetStaticTlsBoundary(addr, size, &align);
528#if defined(__x86_64__) || defined(__i386__) || defined(__s390__) || \
529 defined(__sparc__)
552# if defined(__x86_64__) || defined(__i386__) || defined(__s390__) || \
553 defined(__sparc__)
530554 if (SANITIZER_GLIBC) {
531#if defined(__x86_64__) || defined(__i386__)
555# if defined(__x86_64__) || defined(__i386__)
532556 align = Max<uptr>(align, 64);
533#else
557# else
534558 align = Max<uptr>(align, 16);
535#endif
559# endif
536560 }
537561 const uptr tp = RoundUpTo(*addr + *size, align);
538562
......@@ -551,26 +575,26 @@ static void GetTls(uptr *addr, uptr *size) {
551575 // because the number of bytes after pthread::specific is larger.
552576 *addr = tp - RoundUpTo(*size, align);
553577 *size = tp - *addr + ThreadDescriptorSize();
554#else
578# else
555579 if (SANITIZER_GLIBC)
556580 *size += 1664;
557581 else if (SANITIZER_FREEBSD)
558582 *size += 128; // RTLD_STATIC_TLS_EXTRA
559#if defined(__mips__) || defined(__powerpc64__) || SANITIZER_RISCV64
583# if defined(__mips__) || defined(__powerpc64__) || SANITIZER_RISCV64
560584 const uptr pre_tcb_size = TlsPreTcbSize();
561585 *addr -= pre_tcb_size;
562586 *size += pre_tcb_size;
563#else
587# else
564588 // arm and aarch64 reserve two words at TP, so this underestimates the range.
565589 // However, this is sufficient for the purpose of finding the pointers to
566590 // thread-specific data keys.
567591 const uptr tcb_size = ThreadDescriptorSize();
568592 *addr -= tcb_size;
569593 *size += tcb_size;
570#endif
571#endif
572#elif SANITIZER_NETBSD
573 struct tls_tcb * const tcb = ThreadSelfTlsTcb();
594# endif
595# endif
596# elif SANITIZER_NETBSD
597 struct tls_tcb *const tcb = ThreadSelfTlsTcb();
574598 *addr = 0;
575599 *size = 0;
576600 if (tcb != 0) {
......@@ -583,31 +607,31 @@ static void GetTls(uptr *addr, uptr *size) {
583607 *addr = (uptr)tcb->tcb_dtv[1];
584608 }
585609 }
586#else
587#error "Unknown OS"
588#endif
610# else
611# error "Unknown OS"
612# endif
589613}
590#endif
614# endif
591615
592#if !SANITIZER_GO
616# if !SANITIZER_GO
593617uptr GetTlsSize() {
594#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
595 SANITIZER_SOLARIS
618# if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
619 SANITIZER_SOLARIS
596620 uptr addr, size;
597621 GetTls(&addr, &size);
598622 return size;
599#else
623# else
600624 return 0;
601#endif
625# endif
602626}
603#endif
627# endif
604628
605629void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
606630 uptr *tls_addr, uptr *tls_size) {
607#if SANITIZER_GO
631# if SANITIZER_GO
608632 // Stub implementation for Go.
609633 *stk_addr = *stk_size = *tls_addr = *tls_size = 0;
610#else
634# else
611635 GetTls(tls_addr, tls_size);
612636
613637 uptr stack_top, stack_bottom;
......@@ -623,16 +647,12 @@ void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
623647 *stk_size = *tls_addr - *stk_addr;
624648 }
625649 }
626#endif
650# endif
627651}
628652
629#if !SANITIZER_FREEBSD
653# if !SANITIZER_FREEBSD
630654typedef ElfW(Phdr) Elf_Phdr;
631#elif SANITIZER_WORDSIZE == 32 && __FreeBSD_version <= 902001 // v9.2
632#define Elf_Phdr XElf32_Phdr
633#define dl_phdr_info xdl_phdr_info
634#define dl_iterate_phdr(c, b) xdl_iterate_phdr((c), (b))
635#endif // !SANITIZER_FREEBSD
655# endif
636656
637657struct DlIteratePhdrData {
638658 InternalMmapVectorNoCtor<LoadedModule> *modules;
......@@ -652,8 +672,7 @@ static int AddModuleSegments(const char *module_name, dl_phdr_info *info,
652672 uptr cur_end = cur_beg + phdr->p_memsz;
653673 bool executable = phdr->p_flags & PF_X;
654674 bool writable = phdr->p_flags & PF_W;
655 cur_module.addAddressRange(cur_beg, cur_end, executable,
656 writable);
675 cur_module.addAddressRange(cur_beg, cur_end, executable, writable);
657676 } else if (phdr->p_type == PT_NOTE) {
658677# ifdef NT_GNU_BUILD_ID
659678 uptr off = 0;
......@@ -698,33 +717,30 @@ static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) {
698717 return AddModuleSegments(module_name.data(), info, data->modules);
699718 }
700719
701 if (info->dlpi_name) {
702 InternalScopedString module_name;
703 module_name.append("%s", info->dlpi_name);
704 return AddModuleSegments(module_name.data(), info, data->modules);
705 }
720 if (info->dlpi_name)
721 return AddModuleSegments(info->dlpi_name, info, data->modules);
706722
707723 return 0;
708724}
709725
710#if SANITIZER_ANDROID && __ANDROID_API__ < 21
726# if SANITIZER_ANDROID && __ANDROID_API__ < 21
711727extern "C" __attribute__((weak)) int dl_iterate_phdr(
712728 int (*)(struct dl_phdr_info *, size_t, void *), void *);
713#endif
729# endif
714730
715731static bool requiresProcmaps() {
716#if SANITIZER_ANDROID && __ANDROID_API__ <= 22
732# if SANITIZER_ANDROID && __ANDROID_API__ <= 22
717733 // Fall back to /proc/maps if dl_iterate_phdr is unavailable or broken.
718734 // The runtime check allows the same library to work with
719735 // both K and L (and future) Android releases.
720736 return AndroidGetApiLevel() <= ANDROID_LOLLIPOP_MR1;
721#else
737# else
722738 return false;
723#endif
739# endif
724740}
725741
726742static void procmapsInit(InternalMmapVectorNoCtor<LoadedModule> *modules) {
727 MemoryMappingLayout memory_mapping(/*cache_enabled*/true);
743 MemoryMappingLayout memory_mapping(/*cache_enabled*/ true);
728744 memory_mapping.DumpListOfModules(modules);
729745}
730746
......@@ -776,22 +792,19 @@ uptr GetRSS() {
776792 // We need the second number which is RSS in pages.
777793 char *pos = buf;
778794 // Skip the first number.
779 while (*pos >= '0' && *pos <= '9')
780 pos++;
795 while (*pos >= '0' && *pos <= '9') pos++;
781796 // Skip whitespaces.
782 while (!(*pos >= '0' && *pos <= '9') && *pos != 0)
783 pos++;
797 while (!(*pos >= '0' && *pos <= '9') && *pos != 0) pos++;
784798 // Read the number.
785799 uptr rss = 0;
786 while (*pos >= '0' && *pos <= '9')
787 rss = rss * 10 + *pos++ - '0';
800 while (*pos >= '0' && *pos <= '9') rss = rss * 10 + *pos++ - '0';
788801 return rss * GetPageSizeCached();
789802}
790803
791804// sysconf(_SC_NPROCESSORS_{CONF,ONLN}) cannot be used on most platforms as
792805// they allocate memory.
793806u32 GetNumberOfCPUs() {
794#if SANITIZER_FREEBSD || SANITIZER_NETBSD
807# if SANITIZER_FREEBSD || SANITIZER_NETBSD
795808 u32 ncpu;
796809 int req[2];
797810 uptr len = sizeof(ncpu);
......@@ -799,7 +812,7 @@ u32 GetNumberOfCPUs() {
799812 req[1] = HW_NCPU;
800813 CHECK_EQ(internal_sysctl(req, 2, &ncpu, &len, NULL, 0), 0);
801814 return ncpu;
802#elif SANITIZER_ANDROID && !defined(CPU_COUNT) && !defined(__aarch64__)
815# elif SANITIZER_ANDROID && !defined(CPU_COUNT) && !defined(__aarch64__)
803816 // Fall back to /sys/devices/system/cpu on Android when cpu_set_t doesn't
804817 // exist in sched.h. That is the case for toolchains generated with older
805818 // NDKs.
......@@ -827,26 +840,26 @@ u32 GetNumberOfCPUs() {
827840 break;
828841 if (entry->d_ino != 0 && *d_type == DT_DIR) {
829842 if (entry->d_name[0] == 'c' && entry->d_name[1] == 'p' &&
830 entry->d_name[2] == 'u' &&
831 entry->d_name[3] >= '0' && entry->d_name[3] <= '9')
843 entry->d_name[2] == 'u' && entry->d_name[3] >= '0' &&
844 entry->d_name[3] <= '9')
832845 n_cpus++;
833846 }
834847 entry = (struct linux_dirent *)(((u8 *)entry) + entry->d_reclen);
835848 }
836849 internal_close(fd);
837850 return n_cpus;
838#elif SANITIZER_SOLARIS
851# elif SANITIZER_SOLARIS
839852 return sysconf(_SC_NPROCESSORS_ONLN);
840#else
853# else
841854 cpu_set_t CPUs;
842855 CHECK_EQ(sched_getaffinity(0, sizeof(cpu_set_t), &CPUs), 0);
843856 return CPU_COUNT(&CPUs);
844#endif
857# endif
845858}
846859
847#if SANITIZER_LINUX
860# if SANITIZER_LINUX
848861
849#if SANITIZER_ANDROID
862# if SANITIZER_ANDROID
850863static atomic_uint8_t android_log_initialized;
851864
852865void AndroidLogInit() {
......@@ -858,13 +871,15 @@ static bool ShouldLogAfterPrintf() {
858871 return atomic_load(&android_log_initialized, memory_order_acquire);
859872}
860873
861extern "C" SANITIZER_WEAK_ATTRIBUTE
862int async_safe_write_log(int pri, const char* tag, const char* msg);
863extern "C" SANITIZER_WEAK_ATTRIBUTE
864int __android_log_write(int prio, const char* tag, const char* msg);
874extern "C" SANITIZER_WEAK_ATTRIBUTE int async_safe_write_log(int pri,
875 const char *tag,
876 const char *msg);
877extern "C" SANITIZER_WEAK_ATTRIBUTE int __android_log_write(int prio,
878 const char *tag,
879 const char *msg);
865880
866881// ANDROID_LOG_INFO is 4, but can't be resolved at runtime.
867#define SANITIZER_ANDROID_LOG_INFO 4
882# define SANITIZER_ANDROID_LOG_INFO 4
868883
869884// async_safe_write_log is a new public version of __libc_write_log that is
870885// used behind syslog. It is preferable to syslog as it will not do any dynamic
......@@ -883,14 +898,14 @@ void WriteOneLineToSyslog(const char *s) {
883898 }
884899}
885900
886extern "C" SANITIZER_WEAK_ATTRIBUTE
887void android_set_abort_message(const char *);
901extern "C" SANITIZER_WEAK_ATTRIBUTE void android_set_abort_message(
902 const char *);
888903
889904void SetAbortMessage(const char *str) {
890905 if (&android_set_abort_message)
891906 android_set_abort_message(str);
892907}
893#else
908# else
894909void AndroidLogInit() {}
895910
896911static bool ShouldLogAfterPrintf() { return true; }
......@@ -898,16 +913,16 @@ static bool ShouldLogAfterPrintf() { return true; }
898913void WriteOneLineToSyslog(const char *s) { syslog(LOG_INFO, "%s", s); }
899914
900915void SetAbortMessage(const char *str) {}
901#endif // SANITIZER_ANDROID
916# endif // SANITIZER_ANDROID
902917
903918void LogMessageOnPrintf(const char *str) {
904919 if (common_flags()->log_to_syslog && ShouldLogAfterPrintf())
905920 WriteToSyslog(str);
906921}
907922
908#endif // SANITIZER_LINUX
923# endif // SANITIZER_LINUX
909924
910#if SANITIZER_GLIBC && !SANITIZER_GO
925# if SANITIZER_GLIBC && !SANITIZER_GO
911926// glibc crashes when using clock_gettime from a preinit_array function as the
912927// vDSO function pointers haven't been initialized yet. __progname is
913928// initialized after the vDSO function pointers, so if it exists, is not null
......@@ -918,8 +933,8 @@ inline bool CanUseVDSO() { return &__progname && __progname && *__progname; }
918933// MonotonicNanoTime is a timing function that can leverage the vDSO by calling
919934// clock_gettime. real_clock_gettime only exists if clock_gettime is
920935// intercepted, so define it weakly and use it if available.
921extern "C" SANITIZER_WEAK_ATTRIBUTE
922int real_clock_gettime(u32 clk_id, void *tp);
936extern "C" SANITIZER_WEAK_ATTRIBUTE int real_clock_gettime(u32 clk_id,
937 void *tp);
923938u64 MonotonicNanoTime() {
924939 timespec ts;
925940 if (CanUseVDSO()) {
......@@ -932,19 +947,26 @@ u64 MonotonicNanoTime() {
932947 }
933948 return (u64)ts.tv_sec * (1000ULL * 1000 * 1000) + ts.tv_nsec;
934949}
935#else
950# else
936951// Non-glibc & Go always use the regular function.
937952u64 MonotonicNanoTime() {
938953 timespec ts;
939954 clock_gettime(CLOCK_MONOTONIC, &ts);
940955 return (u64)ts.tv_sec * (1000ULL * 1000 * 1000) + ts.tv_nsec;
941956}
942#endif // SANITIZER_GLIBC && !SANITIZER_GO
957# endif // SANITIZER_GLIBC && !SANITIZER_GO
943958
944959void ReExec() {
945960 const char *pathname = "/proc/self/exe";
946961
947#if SANITIZER_NETBSD
962# if SANITIZER_FREEBSD
963 for (const auto *aux = __elf_aux_vector; aux->a_type != AT_NULL; aux++) {
964 if (aux->a_type == AT_EXECPATH) {
965 pathname = static_cast<const char *>(aux->a_un.a_ptr);
966 break;
967 }
968 }
969# elif SANITIZER_NETBSD
948970 static const int name[] = {
949971 CTL_KERN,
950972 KERN_PROC_ARGS,
......@@ -957,14 +979,14 @@ void ReExec() {
957979 len = sizeof(path);
958980 if (internal_sysctl(name, ARRAY_SIZE(name), path, &len, NULL, 0) != -1)
959981 pathname = path;
960#elif SANITIZER_SOLARIS
982# elif SANITIZER_SOLARIS
961983 pathname = getexecname();
962984 CHECK_NE(pathname, NULL);
963#elif SANITIZER_USE_GETAUXVAL
985# elif SANITIZER_USE_GETAUXVAL
964986 // Calling execve with /proc/self/exe sets that as $EXEC_ORIGIN. Binaries that
965987 // rely on that will fail to load shared libraries. Query AT_EXECFN instead.
966988 pathname = reinterpret_cast<const char *>(getauxval(AT_EXECFN));
967#endif
989# endif
968990
969991 uptr rv = internal_execve(pathname, GetArgv(), GetEnviron());
970992 int rverrno;
......@@ -986,9 +1008,8 @@ void UnmapFromTo(uptr from, uptr to) {
9861008}
9871009
9881010uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale,
989 uptr min_shadow_base_alignment,
990 UNUSED uptr &high_mem_end) {
991 const uptr granularity = GetMmapGranularity();
1011 uptr min_shadow_base_alignment, UNUSED uptr &high_mem_end,
1012 uptr granularity) {
9921013 const uptr alignment =
9931014 Max<uptr>(granularity << shadow_scale, 1ULL << min_shadow_base_alignment);
9941015 const uptr left_padding =
......@@ -1016,14 +1037,14 @@ static uptr MmapSharedNoReserve(uptr addr, uptr size) {
10161037
10171038static uptr MremapCreateAlias(uptr base_addr, uptr alias_addr,
10181039 uptr alias_size) {
1019#if SANITIZER_LINUX
1040# if SANITIZER_LINUX
10201041 return internal_mremap(reinterpret_cast<void *>(base_addr), 0, alias_size,
10211042 MREMAP_MAYMOVE | MREMAP_FIXED,
10221043 reinterpret_cast<void *>(alias_addr));
1023#else
1044# else
10241045 CHECK(false && "mremap is not supported outside of Linux");
10251046 return 0;
1026#endif
1047# endif
10271048}
10281049
10291050static void CreateAliases(uptr start_addr, uptr alias_size, uptr num_aliases) {
......@@ -1068,12 +1089,12 @@ uptr MapDynamicShadowAndAliases(uptr shadow_size, uptr alias_size,
10681089}
10691090
10701091void InitializePlatformCommonFlags(CommonFlags *cf) {
1071#if SANITIZER_ANDROID
1092# if SANITIZER_ANDROID
10721093 if (&__libc_get_static_tls_bounds == nullptr)
10731094 cf->detect_leaks = false;
1074#endif
1095# endif
10751096}
10761097
1077} // namespace __sanitizer
1098} // namespace __sanitizer
10781099
10791100#endif
lib/tsan/sanitizer_common/sanitizer_linux_s390.cpp+79-85
......@@ -15,14 +15,14 @@
1515
1616#if SANITIZER_LINUX && SANITIZER_S390
1717
18#include <dlfcn.h>
19#include <errno.h>
20#include <sys/syscall.h>
21#include <sys/utsname.h>
22#include <unistd.h>
18# include <dlfcn.h>
19# include <errno.h>
20# include <sys/syscall.h>
21# include <sys/utsname.h>
22# include <unistd.h>
2323
24#include "sanitizer_libc.h"
25#include "sanitizer_linux.h"
24# include "sanitizer_libc.h"
25# include "sanitizer_linux.h"
2626
2727namespace __sanitizer {
2828
......@@ -37,22 +37,19 @@ uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd,
3737 unsigned long fd;
3838 unsigned long offset;
3939 } 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
40 (unsigned long)addr, (unsigned long)length, (unsigned long)prot,
41 (unsigned long)flags, (unsigned long)fd,
42# ifdef __s390x__
43 (unsigned long)offset,
44# else
4845 (unsigned long)(offset / 4096),
49# endif
46# endif
5047 };
51# ifdef __s390x__
48# ifdef __s390x__
5249 return syscall(__NR_mmap, &params);
53# else
50# else
5451 return syscall(__NR_mmap2, &params);
55# endif
52# endif
5653}
5754
5855uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
......@@ -63,58 +60,54 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
6360 }
6461 CHECK_EQ(0, (uptr)child_stack % 16);
6562 // Minimum frame size.
66#ifdef __s390x__
63# ifdef __s390x__
6764 child_stack = (char *)child_stack - 160;
68#else
65# else
6966 child_stack = (char *)child_stack - 96;
70#endif
67# endif
7168 // Terminate unwind chain.
7269 ((unsigned long *)child_stack)[0] = 0;
7370 // And pass parameters.
7471 ((unsigned long *)child_stack)[1] = (uptr)fn;
7572 ((unsigned long *)child_stack)[2] = (uptr)arg;
7673 register uptr res __asm__("r2");
77 register void *__cstack __asm__("r2") = child_stack;
78 register long __flags __asm__("r3") = flags;
79 register int * __ptidptr __asm__("r4") = parent_tidptr;
80 register int * __ctidptr __asm__("r5") = child_tidptr;
81 register void * __newtls __asm__("r6") = newtls;
74 register void *__cstack __asm__("r2") = child_stack;
75 register long __flags __asm__("r3") = flags;
76 register int *__ptidptr __asm__("r4") = parent_tidptr;
77 register int *__ctidptr __asm__("r5") = child_tidptr;
78 register void *__newtls __asm__("r6") = newtls;
8279
8380 __asm__ __volatile__(
84 /* Clone. */
85 "svc %1\n"
86
87 /* if (%r2 != 0)
88 * return;
89 */
90#ifdef __s390x__
91 "cghi %%r2, 0\n"
92#else
93 "chi %%r2, 0\n"
94#endif
95 "jne 1f\n"
96
97 /* Call "fn(arg)". */
98#ifdef __s390x__
99 "lmg %%r1, %%r2, 8(%%r15)\n"
100#else
101 "lm %%r1, %%r2, 4(%%r15)\n"
102#endif
103 "basr %%r14, %%r1\n"
104
105 /* Call _exit(%r2). */
106 "svc %2\n"
107
108 /* Return to parent. */
109 "1:\n"
110 : "=r" (res)
111 : "i"(__NR_clone), "i"(__NR_exit),
112 "r"(__cstack),
113 "r"(__flags),
114 "r"(__ptidptr),
115 "r"(__ctidptr),
116 "r"(__newtls)
117 : "memory", "cc");
81 /* Clone. */
82 "svc %1\n"
83
84 /* if (%r2 != 0)
85 * return;
86 */
87# ifdef __s390x__
88 "cghi %%r2, 0\n"
89# else
90 "chi %%r2, 0\n"
91# endif
92 "jne 1f\n"
93
94 /* Call "fn(arg)". */
95# ifdef __s390x__
96 "lmg %%r1, %%r2, 8(%%r15)\n"
97# else
98 "lm %%r1, %%r2, 4(%%r15)\n"
99# endif
100 "basr %%r14, %%r1\n"
101
102 /* Call _exit(%r2). */
103 "svc %2\n"
104
105 /* Return to parent. */
106 "1:\n"
107 : "=r"(res)
108 : "i"(__NR_clone), "i"(__NR_exit), "r"(__cstack), "r"(__flags),
109 "r"(__ptidptr), "r"(__ctidptr), "r"(__newtls)
110 : "memory", "cc");
118111 if (res >= (uptr)-4095) {
119112 errno = -res;
120113 return -1;
......@@ -122,7 +115,7 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
122115 return res;
123116}
124117
125#if SANITIZER_S390_64
118# if SANITIZER_S390_64
126119static bool FixedCVE_2016_2143() {
127120 // Try to determine if the running kernel has a fix for CVE-2016-2143,
128121 // return false if in doubt (better safe than sorry). Distros may want to
......@@ -137,20 +130,20 @@ static bool FixedCVE_2016_2143() {
137130 // At least first 2 should be matched.
138131 if (ptr[0] != '.')
139132 return false;
140 minor = internal_simple_strtoll(ptr+1, &ptr, 10);
133 minor = internal_simple_strtoll(ptr + 1, &ptr, 10);
141134 // Third is optional.
142135 if (ptr[0] == '.')
143 patch = internal_simple_strtoll(ptr+1, &ptr, 10);
136 patch = internal_simple_strtoll(ptr + 1, &ptr, 10);
144137 if (major < 3) {
145138 if (major == 2 && minor == 6 && patch == 32 && ptr[0] == '-' &&
146139 internal_strstr(ptr, ".el6")) {
147140 // Check RHEL6
148 int r1 = internal_simple_strtoll(ptr+1, &ptr, 10);
149 if (r1 >= 657) // 2.6.32-657.el6 or later
141 int r1 = internal_simple_strtoll(ptr + 1, &ptr, 10);
142 if (r1 >= 657) // 2.6.32-657.el6 or later
150143 return true;
151144 if (r1 == 642 && ptr[0] == '.') {
152 int r2 = internal_simple_strtoll(ptr+1, &ptr, 10);
153 if (r2 >= 9) // 2.6.32-642.9.1.el6 or later
145 int r2 = internal_simple_strtoll(ptr + 1, &ptr, 10);
146 if (r2 >= 9) // 2.6.32-642.9.1.el6 or later
154147 return true;
155148 }
156149 }
......@@ -166,12 +159,12 @@ static bool FixedCVE_2016_2143() {
166159 if (minor == 10 && patch == 0 && ptr[0] == '-' &&
167160 internal_strstr(ptr, ".el7")) {
168161 // Check RHEL7
169 int r1 = internal_simple_strtoll(ptr+1, &ptr, 10);
170 if (r1 >= 426) // 3.10.0-426.el7 or later
162 int r1 = internal_simple_strtoll(ptr + 1, &ptr, 10);
163 if (r1 >= 426) // 3.10.0-426.el7 or later
171164 return true;
172165 if (r1 == 327 && ptr[0] == '.') {
173 int r2 = internal_simple_strtoll(ptr+1, &ptr, 10);
174 if (r2 >= 27) // 3.10.0-327.27.1.el7 or later
166 int r2 = internal_simple_strtoll(ptr + 1, &ptr, 10);
167 if (r2 >= 27) // 3.10.0-327.27.1.el7 or later
175168 return true;
176169 }
177170 }
......@@ -187,8 +180,8 @@ static bool FixedCVE_2016_2143() {
187180 if (minor == 4 && patch == 0 && ptr[0] == '-' &&
188181 internal_strstr(buf.version, "Ubuntu")) {
189182 // Check Ubuntu 16.04
190 int r1 = internal_simple_strtoll(ptr+1, &ptr, 10);
191 if (r1 >= 13) // 4.4.0-13 or later
183 int r1 = internal_simple_strtoll(ptr + 1, &ptr, 10);
184 if (r1 >= 13) // 4.4.0-13 or later
192185 return true;
193186 }
194187 // Otherwise, OK if 4.5+.
......@@ -211,18 +204,19 @@ void AvoidCVE_2016_2143() {
211204 if (GetEnv("SANITIZER_IGNORE_CVE_2016_2143"))
212205 return;
213206 Report(
214 "ERROR: Your kernel seems to be vulnerable to CVE-2016-2143. Using ASan,\n"
215 "MSan, TSan, DFSan or LSan with such kernel can and will crash your\n"
216 "machine, or worse.\n"
217 "\n"
218 "If you are certain your kernel is not vulnerable (you have compiled it\n"
219 "yourself, or are using an unrecognized distribution kernel), you can\n"
220 "override this safety check by exporting SANITIZER_IGNORE_CVE_2016_2143\n"
221 "with any value.\n");
207 "ERROR: Your kernel seems to be vulnerable to CVE-2016-2143. Using "
208 "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");
222216 Die();
223217}
224#endif
218# endif
225219
226} // namespace __sanitizer
220} // namespace __sanitizer
227221
228#endif // SANITIZER_LINUX && SANITIZER_S390
222#endif // SANITIZER_LINUX && SANITIZER_S390
lib/tsan/sanitizer_common/sanitizer_mac.cpp+4-4
......@@ -1188,8 +1188,8 @@ uptr GetMaxVirtualAddress() {
11881188}
11891189
11901190uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale,
1191 uptr min_shadow_base_alignment, uptr &high_mem_end) {
1192 const uptr granularity = GetMmapGranularity();
1191 uptr min_shadow_base_alignment, uptr &high_mem_end,
1192 uptr granularity) {
11931193 const uptr alignment =
11941194 Max<uptr>(granularity << shadow_scale, 1ULL << min_shadow_base_alignment);
11951195 const uptr left_padding =
......@@ -1372,8 +1372,8 @@ void DumpProcessMap() {
13721372 for (uptr i = 0; i < modules.size(); ++i) {
13731373 char uuid_str[128];
13741374 FormatUUID(uuid_str, sizeof(uuid_str), modules[i].uuid());
1375 Printf("0x%zx-0x%zx %s (%s) %s\n", modules[i].base_address(),
1376 modules[i].max_address(), modules[i].full_name(),
1375 Printf("%p-%p %s (%s) %s\n", (void *)modules[i].base_address(),
1376 (void *)modules[i].max_address(), modules[i].full_name(),
13771377 ModuleArchToString(modules[i].arch()), uuid_str);
13781378 }
13791379 Printf("End of module map.\n");
lib/tsan/sanitizer_common/sanitizer_mallinfo.h+4
......@@ -31,6 +31,10 @@ struct __sanitizer_struct_mallinfo {
3131 int v[10];
3232};
3333
34struct __sanitizer_struct_mallinfo2 {
35 uptr v[10];
36};
37
3438#endif
3539
3640} // namespace __sanitizer
lib/tsan/sanitizer_common/sanitizer_malloc_mac.inc+1-1
......@@ -123,7 +123,7 @@ INTERCEPTOR(void, malloc_set_zone_name, malloc_zone_t *zone, const char *name) {
123123 COMMON_MALLOC_ENTER();
124124 InternalScopedString new_name;
125125 if (name && zone->introspect == sanitizer_zone.introspect) {
126 new_name.append(COMMON_MALLOC_ZONE_NAME "-%s", name);
126 new_name.AppendF(COMMON_MALLOC_ZONE_NAME "-%s", name);
127127 name = new_name.data();
128128 }
129129
lib/tsan/sanitizer_common/sanitizer_mutex.cpp+4-2
......@@ -212,8 +212,10 @@ struct InternalDeadlockDetector {
212212 return initialized > 0;
213213 }
214214};
215
216static THREADLOCAL InternalDeadlockDetector deadlock_detector;
215// This variable is used by the __tls_get_addr interceptor, so cannot use the
216// global-dynamic TLS model, as that would result in crashes.
217__attribute__((tls_model("initial-exec"))) static THREADLOCAL
218 InternalDeadlockDetector deadlock_detector;
217219
218220void CheckedMutex::LockImpl(uptr pc) { deadlock_detector.Lock(type_, pc); }
219221
lib/tsan/sanitizer_common/sanitizer_placement_new.h+1-3
......@@ -17,8 +17,6 @@
1717
1818#include "sanitizer_internal_defs.h"
1919
20inline void *operator new(__sanitizer::operator_new_size_type sz, void *p) {
21 return p;
22}
20inline void *operator new(__sanitizer::usize sz, void *p) { return p; }
2321
2422#endif // SANITIZER_PLACEMENT_NEW_H
lib/tsan/sanitizer_common/sanitizer_platform.h+22-2
......@@ -260,6 +260,17 @@
260260# define SANITIZER_ARM64 0
261261#endif
262262
263#if SANITIZER_WINDOWS64 && SANITIZER_ARM64
264# define SANITIZER_WINDOWS_ARM64 1
265# define SANITIZER_WINDOWS_x64 0
266#elif SANITIZER_WINDOWS64 && !SANITIZER_ARM64
267# define SANITIZER_WINDOWS_ARM64 0
268# define SANITIZER_WINDOWS_x64 1
269#else
270# define SANITIZER_WINDOWS_ARM64 0
271# define SANITIZER_WINDOWS_x64 0
272#endif
273
263274#if SANITIZER_SOLARIS && SANITIZER_WORDSIZE == 32
264275# define SANITIZER_SOLARIS32 1
265276#else
......@@ -284,7 +295,8 @@
284295// For such platforms build this code with -DSANITIZER_CAN_USE_ALLOCATOR64=0 or
285296// change the definition of SANITIZER_CAN_USE_ALLOCATOR64 here.
286297#ifndef SANITIZER_CAN_USE_ALLOCATOR64
287# if SANITIZER_RISCV64 || SANITIZER_IOS
298# if (SANITIZER_RISCV64 && !SANITIZER_FUCHSIA && !SANITIZER_LINUX) || \
299 SANITIZER_IOS || SANITIZER_DRIVERKIT
288300# define SANITIZER_CAN_USE_ALLOCATOR64 0
289301# elif defined(__mips64) || defined(__hexagon__)
290302# define SANITIZER_CAN_USE_ALLOCATOR64 0
......@@ -303,7 +315,15 @@
303315# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 40)
304316# endif
305317#elif SANITIZER_RISCV64
306# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 38)
318// FIXME: Rather than hardcoding the VMA here, we should rely on
319// GetMaxUserVirtualAddress(). This will require some refactoring though since
320// many places either hardcode some value or SANITIZER_MMAP_RANGE_SIZE is
321// assumed to be some constant integer.
322# if SANITIZER_FUCHSIA
323# define SANITIZER_MMAP_RANGE_SIZE (1ULL << 38)
324# else
325# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 56)
326# endif
307327#elif defined(__aarch64__)
308328# if SANITIZER_APPLE
309329# if SANITIZER_OSX || SANITIZER_IOSSIM
lib/tsan/sanitizer_common/sanitizer_platform_interceptors.h+10-6
......@@ -191,7 +191,8 @@
191191
192192#define SANITIZER_INTERCEPT_PREADV \
193193 (SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID)
194#define SANITIZER_INTERCEPT_PWRITEV SI_LINUX_NOT_ANDROID
194#define SANITIZER_INTERCEPT_PWRITEV \
195 (SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID)
195196#define SANITIZER_INTERCEPT_PREADV64 SI_GLIBC
196197#define SANITIZER_INTERCEPT_PWRITEV64 SI_GLIBC
197198
......@@ -301,7 +302,8 @@
301302#define SANITIZER_INTERCEPT_CANONICALIZE_FILE_NAME (SI_GLIBC || SI_SOLARIS)
302303#define SANITIZER_INTERCEPT_CONFSTR \
303304 (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
304#define SANITIZER_INTERCEPT_SCHED_GETAFFINITY SI_LINUX_NOT_ANDROID
305#define SANITIZER_INTERCEPT_SCHED_GETAFFINITY \
306 (SI_LINUX_NOT_ANDROID || SI_FREEBSD)
305307#define SANITIZER_INTERCEPT_SCHED_GETPARAM SI_LINUX_NOT_ANDROID || SI_SOLARIS
306308#define SANITIZER_INTERCEPT_STRERROR SI_POSIX
307309#define SANITIZER_INTERCEPT_STRERROR_R SI_POSIX
......@@ -462,7 +464,7 @@
462464 (SI_LINUX || SI_MAC || SI_WINDOWS || SI_FREEBSD || SI_NETBSD || SI_SOLARIS)
463465#define SANITIZER_INTERCEPT_RECV_RECVFROM SI_POSIX
464466#define SANITIZER_INTERCEPT_SEND_SENDTO SI_POSIX
465#define SANITIZER_INTERCEPT_EVENTFD_READ_WRITE SI_LINUX
467#define SANITIZER_INTERCEPT_EVENTFD_READ_WRITE (SI_LINUX || SI_FREEBSD)
466468
467469#define SI_STAT_LINUX (SI_LINUX && __GLIBC_PREREQ(2, 33))
468470#define SANITIZER_INTERCEPT_STAT \
......@@ -575,12 +577,12 @@
575577#define SANITIZER_INTERCEPT_SL_INIT (SI_FREEBSD || SI_NETBSD)
576578
577579#define SANITIZER_INTERCEPT_GETRANDOM \
578 ((SI_LINUX && __GLIBC_PREREQ(2, 25)) || SI_FREEBSD)
580 ((SI_LINUX && __GLIBC_PREREQ(2, 25)) || SI_FREEBSD || SI_SOLARIS)
579581#define SANITIZER_INTERCEPT___CXA_ATEXIT SI_NETBSD
580582#define SANITIZER_INTERCEPT_ATEXIT SI_NETBSD
581583#define SANITIZER_INTERCEPT_PTHREAD_ATFORK SI_NETBSD
582584#define SANITIZER_INTERCEPT_GETENTROPY \
583 ((SI_LINUX && __GLIBC_PREREQ(2, 25)) || SI_FREEBSD)
585 ((SI_LINUX && __GLIBC_PREREQ(2, 25)) || SI_FREEBSD || SI_SOLARIS)
584586#define SANITIZER_INTERCEPT_QSORT \
585587 (SI_POSIX && !SI_IOSSIM && !SI_WATCHOS && !SI_TVOS && !SI_ANDROID)
586588#define SANITIZER_INTERCEPT_QSORT_R SI_GLIBC
......@@ -594,9 +596,11 @@
594596#define SANITIZER_INTERCEPT___XUNAME SI_FREEBSD
595597#define SANITIZER_INTERCEPT_FLOPEN SI_FREEBSD
596598#define SANITIZER_INTERCEPT_PROCCTL SI_FREEBSD
597#define SANITIZER_INTERCEPT_HEXDUMP SI_FREEBSD
598599#define SANITIZER_INTERCEPT_ARGP_PARSE SI_GLIBC
599600#define SANITIZER_INTERCEPT_CPUSET_GETAFFINITY SI_FREEBSD
601// FIXME: also available from musl 1.2.5
602#define SANITIZER_INTERCEPT_PREADV2 (SI_LINUX && __GLIBC_PREREQ(2, 26))
603#define SANITIZER_INTERCEPT_PWRITEV2 (SI_LINUX && __GLIBC_PREREQ(2, 26))
600604
601605// This macro gives a way for downstream users to override the above
602606// interceptor macros irrespective of the platform they are on. They have
lib/tsan/sanitizer_common/sanitizer_platform_limits_freebsd.cpp+2
......@@ -475,6 +475,8 @@ CHECK_TYPE_SIZE(nfds_t);
475475CHECK_TYPE_SIZE(sigset_t);
476476
477477COMPILER_CHECK(sizeof(__sanitizer_sigaction) == sizeof(struct sigaction));
478COMPILER_CHECK(sizeof(__sanitizer_siginfo) == sizeof(siginfo_t));
479CHECK_SIZE_AND_OFFSET(siginfo_t, si_value);
478480// Can't write checks for sa_handler and sa_sigaction due to them being
479481// preprocessor macros.
480482CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_mask);
lib/tsan/sanitizer_common/sanitizer_platform_limits_freebsd.h+22-2
......@@ -301,11 +301,29 @@ struct __sanitizer_sigset_t {
301301
302302typedef __sanitizer_sigset_t __sanitizer_kernel_sigset_t;
303303
304union __sanitizer_sigval {
305 int sival_int;
306 void *sival_ptr;
307};
308
304309struct __sanitizer_siginfo {
305 // The size is determined by looking at sizeof of real siginfo_t on linux.
306 u64 opaque[128 / sizeof(u64)];
310 int si_signo;
311 int si_errno;
312 int si_code;
313 pid_t si_pid;
314 u32 si_uid;
315 int si_status;
316 void *si_addr;
317 union __sanitizer_sigval si_value;
318# if SANITIZER_WORDSIZE == 64
319 char data[40];
320# else
321 char data[32];
322# endif
307323};
308324
325typedef __sanitizer_siginfo __sanitizer_siginfo_t;
326
309327using __sanitizer_sighandler_ptr = void (*)(int sig);
310328using __sanitizer_sigactionhandler_ptr = void (*)(int sig,
311329 __sanitizer_siginfo *siginfo,
......@@ -726,6 +744,8 @@ struct __sanitizer_cpuset {
726744
727745typedef struct __sanitizer_cpuset __sanitizer_cpuset_t;
728746extern unsigned struct_cpuset_sz;
747
748typedef unsigned long long __sanitizer_eventfd_t;
729749} // namespace __sanitizer
730750
731751# define CHECK_TYPE_SIZE(TYPE) \
lib/tsan/sanitizer_common/sanitizer_platform_limits_openbsd.cpp deleted
lib/tsan/sanitizer_common/sanitizer_platform_limits_openbsd.h deleted
lib/tsan/sanitizer_common/sanitizer_platform_limits_posix.h+1
......@@ -523,6 +523,7 @@ typedef long __sanitizer_clock_t;
523523
524524#if SANITIZER_LINUX
525525typedef int __sanitizer_clockid_t;
526typedef unsigned long long __sanitizer_eventfd_t;
526527#endif
527528
528529#if SANITIZER_LINUX
lib/tsan/sanitizer_common/sanitizer_posix.cpp+6-6
......@@ -54,12 +54,12 @@ void *MmapOrDie(uptr size, const char *mem_type, bool raw_report) {
5454 return (void *)res;
5555}
5656
57void UnmapOrDie(void *addr, uptr size) {
57void UnmapOrDie(void *addr, uptr size, bool raw_report) {
5858 if (!addr || !size) return;
5959 uptr res = internal_munmap(addr, size);
6060 int reserrno;
6161 if (UNLIKELY(internal_iserror(res, &reserrno)))
62 ReportMunmapFailureAndDie(addr, size, reserrno);
62 ReportMunmapFailureAndDie(addr, size, reserrno, raw_report);
6363 DecreaseTotalMmap(size);
6464}
6565
......@@ -85,8 +85,8 @@ void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment,
8585 CHECK(IsPowerOfTwo(size));
8686 CHECK(IsPowerOfTwo(alignment));
8787 uptr map_size = size + alignment;
88 // mmap maps entire pages and rounds up map_size needs to be a an integral
89 // number of pages.
88 // mmap maps entire pages and rounds up map_size needs to be a an integral
89 // number of pages.
9090 // We need to be aware of this size for calculating end and for unmapping
9191 // fragments before and after the alignment region.
9292 map_size = RoundUpTo(map_size, GetPageSizeCached());
......@@ -130,8 +130,8 @@ static void *MmapFixedImpl(uptr fixed_addr, uptr size, bool tolerate_enomem,
130130 if (tolerate_enomem && reserrno == ENOMEM)
131131 return nullptr;
132132 char mem_type[40];
133 internal_snprintf(mem_type, sizeof(mem_type), "memory at address 0x%zx",
134 fixed_addr);
133 internal_snprintf(mem_type, sizeof(mem_type), "memory at address %p",
134 (void *)fixed_addr);
135135 ReportMmapFailureAndDie(size, mem_type, "allocate", reserrno);
136136 }
137137 IncreaseTotalMmap(size);
lib/tsan/sanitizer_common/sanitizer_posix.h+14-14
......@@ -74,21 +74,21 @@ int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp,
7474// These functions call appropriate pthread_ functions directly, bypassing
7575// the interceptor. They are weak and may not be present in some tools.
7676SANITIZER_WEAK_ATTRIBUTE
77int real_pthread_create(void *th, void *attr, void *(*callback)(void *),
78 void *param);
77int internal_pthread_create(void *th, void *attr, void *(*callback)(void *),
78 void *param);
7979SANITIZER_WEAK_ATTRIBUTE
80int real_pthread_join(void *th, void **ret);
81
82#define DEFINE_REAL_PTHREAD_FUNCTIONS \
83 namespace __sanitizer { \
84 int real_pthread_create(void *th, void *attr, void *(*callback)(void *), \
85 void *param) { \
86 return REAL(pthread_create)(th, attr, callback, param); \
87 } \
88 int real_pthread_join(void *th, void **ret) { \
89 return REAL(pthread_join(th, ret)); \
90 } \
91 } // namespace __sanitizer
80int internal_pthread_join(void *th, void **ret);
81
82# define DEFINE_INTERNAL_PTHREAD_FUNCTIONS \
83 namespace __sanitizer { \
84 int internal_pthread_create(void *th, void *attr, \
85 void *(*callback)(void *), void *param) { \
86 return REAL(pthread_create)(th, attr, callback, param); \
87 } \
88 int internal_pthread_join(void *th, void **ret) { \
89 return REAL(pthread_join(th, ret)); \
90 } \
91 } // namespace __sanitizer
9292
9393int internal_pthread_attr_getstack(void *attr, void **addr, uptr *size);
9494
lib/tsan/sanitizer_common/sanitizer_posix_libcdep.cpp+27-6
......@@ -91,12 +91,12 @@ static rlim_t getlim(int res) {
9191
9292static void setlim(int res, rlim_t lim) {
9393 struct rlimit rlim;
94 if (getrlimit(res, const_cast<struct rlimit *>(&rlim))) {
94 if (getrlimit(res, &rlim)) {
9595 Report("ERROR: %s getrlimit() failed %d\n", SanitizerToolName, errno);
9696 Die();
9797 }
9898 rlim.rlim_cur = lim;
99 if (setrlimit(res, const_cast<struct rlimit *>(&rlim))) {
99 if (setrlimit(res, &rlim)) {
100100 Report("ERROR: %s setrlimit() failed %d\n", SanitizerToolName, errno);
101101 Die();
102102 }
......@@ -104,7 +104,27 @@ static void setlim(int res, rlim_t lim) {
104104
105105void DisableCoreDumperIfNecessary() {
106106 if (common_flags()->disable_coredump) {
107 setlim(RLIMIT_CORE, 0);
107 rlimit rlim;
108 CHECK_EQ(0, getrlimit(RLIMIT_CORE, &rlim));
109 // On Linux, if the kernel.core_pattern sysctl starts with a '|' (i.e. it
110 // is being piped to a coredump handler such as systemd-coredumpd), the
111 // kernel ignores RLIMIT_CORE (since we aren't creating a file in the file
112 // system) except for the magic value of 1, which disables coredumps when
113 // piping. 1 byte is too small for any kind of valid core dump, so it
114 // also disables coredumps if kernel.core_pattern creates files directly.
115 // While most piped coredump handlers do respect the crashing processes'
116 // RLIMIT_CORE, this is notable not the case for Debian's systemd-coredump
117 // due to a local patch that changes sysctl.d/50-coredump.conf to ignore
118 // the specified limit and instead use RLIM_INFINITY.
119 //
120 // The alternative to using RLIMIT_CORE=1 would be to use prctl() with the
121 // PR_SET_DUMPABLE flag, however that also prevents ptrace(), so makes it
122 // impossible to attach a debugger.
123 //
124 // Note: we use rlim_max in the Min() call here since that is the upper
125 // limit for what can be set without getting an EINVAL error.
126 rlim.rlim_cur = Min<rlim_t>(SANITIZER_LINUX ? 1 : 0, rlim.rlim_max);
127 CHECK_EQ(0, setrlimit(RLIMIT_CORE, &rlim));
108128 }
109129}
110130
......@@ -307,9 +327,10 @@ static bool MmapFixed(uptr fixed_addr, uptr size, int additional_flags,
307327 MAP_PRIVATE | MAP_FIXED | additional_flags | MAP_ANON, name);
308328 int reserrno;
309329 if (internal_iserror(p, &reserrno)) {
310 Report("ERROR: %s failed to "
311 "allocate 0x%zx (%zd) bytes at address %zx (errno: %d)\n",
312 SanitizerToolName, size, size, fixed_addr, reserrno);
330 Report(
331 "ERROR: %s failed to "
332 "allocate 0x%zx (%zd) bytes at address %p (errno: %d)\n",
333 SanitizerToolName, size, size, (void *)fixed_addr, reserrno);
313334 return false;
314335 }
315336 IncreaseTotalMmap(size);
lib/tsan/sanitizer_common/sanitizer_printf.cpp+9-2
......@@ -54,7 +54,7 @@ static int AppendNumber(char **buff, const char *buff_end, u64 absolute_value,
5454 uptr num_buffer[kMaxLen];
5555 int pos = 0;
5656 do {
57 RAW_CHECK_MSG((uptr)pos < kMaxLen, "AppendNumber buffer overflow");
57 RAW_CHECK_MSG((uptr)pos < kMaxLen, "AppendNumber buffer overflow",);
5858 num_buffer[pos++] = absolute_value % base;
5959 absolute_value /= base;
6060 } while (absolute_value > 0);
......@@ -337,7 +337,14 @@ int internal_snprintf(char *buffer, uptr length, const char *format, ...) {
337337 return needed_length;
338338}
339339
340void InternalScopedString::append(const char *format, ...) {
340void InternalScopedString::Append(const char *str) {
341 uptr prev_len = length();
342 uptr str_len = internal_strlen(str);
343 buffer_.resize(prev_len + str_len + 1);
344 internal_memcpy(buffer_.data() + prev_len, str, str_len + 1);
345}
346
347void InternalScopedString::AppendF(const char *format, ...) {
341348 uptr prev_len = length();
342349
343350 while (true) {
lib/tsan/sanitizer_common/sanitizer_procmaps_bsd.cpp+25-22
......@@ -13,9 +13,6 @@
1313#include "sanitizer_platform.h"
1414#if SANITIZER_FREEBSD || SANITIZER_NETBSD
1515#include "sanitizer_common.h"
16#if SANITIZER_FREEBSD
17#include "sanitizer_freebsd.h"
18#endif
1916#include "sanitizer_procmaps.h"
2017
2118// clang-format off
......@@ -29,29 +26,35 @@
2926
3027#include <limits.h>
3128
32// Fix 'kinfo_vmentry' definition on FreeBSD prior v9.2 in 32-bit mode.
33#if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32)
34#include <osreldate.h>
35#if __FreeBSD_version <= 902001 // v9.2
36#define kinfo_vmentry xkinfo_vmentry
37#endif
38#endif
39
4029namespace __sanitizer {
4130
4231#if SANITIZER_FREEBSD
4332void GetMemoryProfile(fill_profile_f cb, uptr *stats) {
44 const int Mib[] = {
45 CTL_KERN,
46 KERN_PROC,
47 KERN_PROC_PID,
48 getpid()
49 };
50
51 struct kinfo_proc InfoProc;
52 uptr Len = sizeof(InfoProc);
53 CHECK_EQ(internal_sysctl(Mib, ARRAY_SIZE(Mib), nullptr, (uptr *)&InfoProc, &Len, 0), 0);
54 cb(0, InfoProc.ki_rssize * GetPageSizeCached(), false, stats);
33 const int Mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()};
34
35 struct kinfo_proc *InfoProc;
36 uptr Len = sizeof(*InfoProc);
37 uptr Size = Len;
38 InfoProc = (struct kinfo_proc *)MmapOrDie(Size, "GetMemoryProfile()");
39 CHECK_EQ(
40 internal_sysctl(Mib, ARRAY_SIZE(Mib), nullptr, (uptr *)InfoProc, &Len, 0),
41 0);
42 cb(0, InfoProc->ki_rssize * GetPageSizeCached(), false, stats);
43 UnmapOrDie(InfoProc, Size, true);
44}
45#elif SANITIZER_NETBSD
46void GetMemoryProfile(fill_profile_f cb, uptr *stats) {
47 struct kinfo_proc2 *InfoProc;
48 uptr Len = sizeof(*InfoProc);
49 uptr Size = Len;
50 const int Mib[] = {CTL_KERN, KERN_PROC2, KERN_PROC_PID,
51 getpid(), (int)Size, 1};
52 InfoProc = (struct kinfo_proc2 *)MmapOrDie(Size, "GetMemoryProfile()");
53 CHECK_EQ(
54 internal_sysctl(Mib, ARRAY_SIZE(Mib), nullptr, (uptr *)InfoProc, &Len, 0),
55 0);
56 cb(0, InfoProc->p_vm_rssize * GetPageSizeCached(), false, stats);
57 UnmapOrDie(InfoProc, Size, true);
5558}
5659#endif
5760
lib/tsan/sanitizer_common/sanitizer_procmaps_common.cpp+1-1
......@@ -145,7 +145,7 @@ void MemoryMappingLayout::DumpListOfModules(
145145 }
146146}
147147
148#if SANITIZER_LINUX || SANITIZER_ANDROID || SANITIZER_SOLARIS || SANITIZER_NETBSD
148#if SANITIZER_LINUX || SANITIZER_ANDROID || SANITIZER_SOLARIS
149149void GetMemoryProfile(fill_profile_f cb, uptr *stats) {
150150 char *smaps = nullptr;
151151 uptr smaps_cap = 0;
lib/tsan/sanitizer_common/sanitizer_ptrauth.h+24-22
......@@ -9,31 +9,33 @@
99#ifndef SANITIZER_PTRAUTH_H
1010#define SANITIZER_PTRAUTH_H
1111
12#if __has_feature(ptrauth_calls)
13#include <ptrauth.h>
12#if __has_feature(ptrauth_intrinsics)
13# include <ptrauth.h>
1414#elif defined(__ARM_FEATURE_PAC_DEFAULT) && !defined(__APPLE__)
15inline unsigned long ptrauth_strip(void* __value, unsigned int __key) {
16 // On the stack the link register is protected with Pointer
17 // Authentication Code when compiled with -mbranch-protection.
18 // Let's stripping the PAC unconditionally because xpaclri is in
19 // the NOP space so will do nothing when it is not enabled or not available.
20 unsigned long ret;
21 asm volatile(
22 "mov x30, %1\n\t"
23 "hint #7\n\t" // xpaclri
24 "mov %0, x30\n\t"
25 : "=r"(ret)
26 : "r"(__value)
27 : "x30");
28 return ret;
29}
30#define ptrauth_auth_data(__value, __old_key, __old_data) __value
31#define ptrauth_string_discriminator(__string) ((int)0)
15// On the stack the link register is protected with Pointer
16// Authentication Code when compiled with -mbranch-protection.
17// Let's stripping the PAC unconditionally because xpaclri is in
18// the NOP space so will do nothing when it is not enabled or not available.
19# define ptrauth_strip(__value, __key) \
20 ({ \
21 __typeof(__value) ret; \
22 asm volatile( \
23 "mov x30, %1\n\t" \
24 "hint #7\n\t" \
25 "mov %0, x30\n\t" \
26 "mov x30, xzr\n\t" \
27 : "=r"(ret) \
28 : "r"(__value) \
29 : "x30"); \
30 ret; \
31 })
32# define ptrauth_auth_data(__value, __old_key, __old_data) __value
33# define ptrauth_string_discriminator(__string) ((int)0)
3234#else
3335// Copied from <ptrauth.h>
34#define ptrauth_strip(__value, __key) __value
35#define ptrauth_auth_data(__value, __old_key, __old_data) __value
36#define ptrauth_string_discriminator(__string) ((int)0)
36# define ptrauth_strip(__value, __key) __value
37# define ptrauth_auth_data(__value, __old_key, __old_data) __value
38# define ptrauth_string_discriminator(__string) ((int)0)
3739#endif
3840
3941#define STRIP_PAC_PC(pc) ((uptr)ptrauth_strip(pc, 0))
lib/tsan/sanitizer_common/sanitizer_redefine_builtins.h+10-6
......@@ -11,16 +11,19 @@
1111//
1212//===----------------------------------------------------------------------===//
1313#ifndef SANITIZER_COMMON_NO_REDEFINE_BUILTINS
14#ifndef SANITIZER_REDEFINE_BUILTINS_H
15#define SANITIZER_REDEFINE_BUILTINS_H
14# ifndef SANITIZER_REDEFINE_BUILTINS_H
15# define SANITIZER_REDEFINE_BUILTINS_H
1616
1717// The asm hack only works with GCC and Clang.
18#if !defined(_WIN32)
18# if !defined(_WIN32)
1919
2020asm("memcpy = __sanitizer_internal_memcpy");
2121asm("memmove = __sanitizer_internal_memmove");
2222asm("memset = __sanitizer_internal_memset");
2323
24# if defined(__cplusplus) && \
25 !defined(SANITIZER_COMMON_REDEFINE_BUILTINS_IN_STD)
26
2427// The builtins should not be redefined in source files that make use of C++
2528// standard libraries, in particular where C++STL headers with inline functions
2629// are used. The redefinition in such cases would lead to ODR violations.
......@@ -46,7 +49,8 @@ using unordered_set = Define_SANITIZER_COMMON_NO_REDEFINE_BUILTINS_in_cpp_file;
4649using vector = Define_SANITIZER_COMMON_NO_REDEFINE_BUILTINS_in_cpp_file;
4750} // namespace std
4851
49#endif // !_WIN32
52# endif // __cpluplus
53# endif // !_WIN32
5054
51#endif // SANITIZER_REDEFINE_BUILTINS_H
52#endif // SANITIZER_COMMON_NO_REDEFINE_BUILTINS
55# endif // SANITIZER_REDEFINE_BUILTINS_H
56#endif // SANITIZER_COMMON_NO_REDEFINE_BUILTINS
lib/tsan/sanitizer_common/sanitizer_ring_buffer.h+3-1
......@@ -47,7 +47,9 @@ class RingBuffer {
4747 void push(T t) {
4848 *next_ = t;
4949 next_--;
50 // The condition below works only if sizeof(T) is divisible by sizeof(T*).
50 static_assert((sizeof(T) % sizeof(T *)) == 0,
51 "The condition below works only if sizeof(T) is divisible by "
52 "sizeof(T*).");
5153 if (next_ <= reinterpret_cast<T*>(&next_))
5254 next_ = last_;
5355 }
lib/tsan/sanitizer_common/sanitizer_stack_store.cpp+7-2
......@@ -44,6 +44,9 @@ StackStore::Id StackStore::Store(const StackTrace &trace, uptr *pack) {
4444 uptr idx = 0;
4545 *pack = 0;
4646 uptr *stack_trace = Alloc(h.size + 1, &idx, pack);
47 // No more space.
48 if (stack_trace == nullptr)
49 return 0;
4750 *stack_trace = h.ToUptr();
4851 internal_memcpy(stack_trace + 1, trace.trace, h.size * sizeof(uptr));
4952 *pack += blocks_[GetBlockIdx(idx)].Stored(h.size + 1);
......@@ -76,8 +79,10 @@ uptr *StackStore::Alloc(uptr count, uptr *idx, uptr *pack) {
7679 uptr block_idx = GetBlockIdx(start);
7780 uptr last_idx = GetBlockIdx(start + count - 1);
7881 if (LIKELY(block_idx == last_idx)) {
79 // Fits into the a single block.
80 CHECK_LT(block_idx, ARRAY_SIZE(blocks_));
82 // Fits into a single block.
83 // No more available blocks. Indicate inability to allocate more memory.
84 if (block_idx >= ARRAY_SIZE(blocks_))
85 return nullptr;
8186 *idx = start;
8287 return blocks_[block_idx].GetOrCreate(this) + GetInBlockIdx(start);
8388 }
lib/tsan/sanitizer_common/sanitizer_stackdepot.cpp+4-4
......@@ -215,16 +215,16 @@ StackTrace StackDepotGet(u32 id) {
215215 return theDepot.Get(id);
216216}
217217
218void StackDepotLockAll() {
219 theDepot.LockAll();
218void StackDepotLockBeforeFork() {
219 theDepot.LockBeforeFork();
220220 compress_thread.LockAndStop();
221221 stackStore.LockAll();
222222}
223223
224void StackDepotUnlockAll() {
224void StackDepotUnlockAfterFork(bool fork_child) {
225225 stackStore.UnlockAll();
226226 compress_thread.Unlock();
227 theDepot.UnlockAll();
227 theDepot.UnlockAfterFork(fork_child);
228228}
229229
230230void StackDepotPrintAll() {
lib/tsan/sanitizer_common/sanitizer_stackdepot.h+2-2
......@@ -39,8 +39,8 @@ StackDepotHandle StackDepotPut_WithHandle(StackTrace stack);
3939// Retrieves a stored stack trace by the id.
4040StackTrace StackDepotGet(u32 id);
4141
42void StackDepotLockAll();
43void StackDepotUnlockAll();
42void StackDepotLockBeforeFork();
43void StackDepotUnlockAfterFork(bool fork_child);
4444void StackDepotPrintAll();
4545void StackDepotStopBackgroundThread();
4646
lib/tsan/sanitizer_common/sanitizer_stackdepotbase.h+23-8
......@@ -52,8 +52,8 @@ class StackDepotBase {
5252 };
5353 }
5454
55 void LockAll();
56 void UnlockAll();
55 void LockBeforeFork();
56 void UnlockAfterFork(bool fork_child);
5757 void PrintAll();
5858
5959 void TestOnlyUnmap() {
......@@ -160,18 +160,33 @@ StackDepotBase<Node, kReservedBits, kTabSizeLog>::Get(u32 id) {
160160}
161161
162162template <class Node, int kReservedBits, int kTabSizeLog>
163void StackDepotBase<Node, kReservedBits, kTabSizeLog>::LockAll() {
164 for (int i = 0; i < kTabSize; ++i) {
165 lock(&tab[i]);
166 }
163void StackDepotBase<Node, kReservedBits, kTabSizeLog>::LockBeforeFork() {
164 // Do not lock hash table. It's very expensive, but it's not rely needed. The
165 // parent process will neither lock nor unlock. Child process risks to be
166 // deadlocked on already locked buckets. To avoid deadlock we will unlock
167 // every locked buckets in `UnlockAfterFork`. This may affect consistency of
168 // the hash table, but the only issue is a few items inserted by parent
169 // process will be not found by child, and the child may insert them again,
170 // wasting some space in `stackStore`.
171
172 // We still need to lock nodes.
173 nodes.Lock();
167174}
168175
169176template <class Node, int kReservedBits, int kTabSizeLog>
170void StackDepotBase<Node, kReservedBits, kTabSizeLog>::UnlockAll() {
177void StackDepotBase<Node, kReservedBits, kTabSizeLog>::UnlockAfterFork(
178 bool fork_child) {
179 nodes.Unlock();
180
181 // Only unlock in child process to avoid deadlock. See `LockBeforeFork`.
182 if (!fork_child)
183 return;
184
171185 for (int i = 0; i < kTabSize; ++i) {
172186 atomic_uint32_t *p = &tab[i];
173187 uptr s = atomic_load(p, memory_order_relaxed);
174 unlock(p, s & kUnlockMask);
188 if (s & kLockMask)
189 unlock(p, s & kUnlockMask);
175190 }
176191}
177192
lib/tsan/sanitizer_common/sanitizer_stacktrace_libcdep.cpp+22-20
......@@ -29,42 +29,43 @@ class StackTraceTextPrinter {
2929 frame_delimiter_(frame_delimiter),
3030 output_(output),
3131 dedup_token_(dedup_token),
32 symbolize_(RenderNeedsSymbolization(stack_trace_fmt)) {}
32 symbolize_(StackTracePrinter::GetOrInit()->RenderNeedsSymbolization(
33 stack_trace_fmt)) {}
3334
3435 bool ProcessAddressFrames(uptr pc) {
35 SymbolizedStack *frames = symbolize_
36 ? Symbolizer::GetOrInit()->SymbolizePC(pc)
37 : SymbolizedStack::New(pc);
36 SymbolizedStackHolder symbolized_stack(
37 symbolize_ ? Symbolizer::GetOrInit()->SymbolizePC(pc)
38 : SymbolizedStack::New(pc));
39 const SymbolizedStack *frames = symbolized_stack.get();
3840 if (!frames)
3941 return false;
4042
41 for (SymbolizedStack *cur = frames; cur; cur = cur->next) {
43 for (const SymbolizedStack *cur = frames; cur; cur = cur->next) {
4244 uptr prev_len = output_->length();
43 RenderFrame(output_, stack_trace_fmt_, frame_num_++, cur->info.address,
44 symbolize_ ? &cur->info : nullptr,
45 common_flags()->symbolize_vs_style,
46 common_flags()->strip_path_prefix);
45 StackTracePrinter::GetOrInit()->RenderFrame(
46 output_, stack_trace_fmt_, frame_num_++, cur->info.address,
47 symbolize_ ? &cur->info : nullptr, common_flags()->symbolize_vs_style,
48 common_flags()->strip_path_prefix);
4749
4850 if (prev_len != output_->length())
49 output_->append("%c", frame_delimiter_);
51 output_->AppendF("%c", frame_delimiter_);
5052
5153 ExtendDedupToken(cur);
5254 }
53 frames->ClearAll();
5455 return true;
5556 }
5657
5758 private:
5859 // Extend the dedup token by appending a new frame.
59 void ExtendDedupToken(SymbolizedStack *stack) {
60 void ExtendDedupToken(const SymbolizedStack *stack) {
6061 if (!dedup_token_)
6162 return;
6263
6364 if (dedup_frames_-- > 0) {
6465 if (dedup_token_->length())
65 dedup_token_->append("--");
66 if (stack->info.function != nullptr)
67 dedup_token_->append("%s", stack->info.function);
66 dedup_token_->Append("--");
67 if (stack->info.function)
68 dedup_token_->Append(stack->info.function);
6869 }
6970 }
7071
......@@ -98,7 +99,7 @@ void StackTrace::PrintTo(InternalScopedString *output) const {
9899 output, &dedup_token);
99100
100101 if (trace == nullptr || size == 0) {
101 output->append(" <empty stack>\n\n");
102 output->Append(" <empty stack>\n\n");
102103 return;
103104 }
104105
......@@ -110,11 +111,11 @@ void StackTrace::PrintTo(InternalScopedString *output) const {
110111 }
111112
112113 // Always add a trailing empty line after stack trace.
113 output->append("\n");
114 output->Append("\n");
114115
115116 // Append deduplication token, if non-empty.
116117 if (dedup_token.length())
117 output->append("DEDUP_TOKEN: %s\n", dedup_token.data());
118 output->AppendF("DEDUP_TOKEN: %s\n", dedup_token.data());
118119}
119120
120121uptr StackTrace::PrintTo(char *out_buf, uptr out_buf_size) const {
......@@ -197,7 +198,7 @@ void __sanitizer_symbolize_pc(uptr pc, const char *fmt, char *out_buf,
197198 StackTraceTextPrinter printer(fmt, '\0', &output, nullptr);
198199 if (!printer.ProcessAddressFrames(pc)) {
199200 output.clear();
200 output.append("<can't symbolize>");
201 output.Append("<can't symbolize>");
201202 }
202203 CopyStringToBuffer(output, out_buf, out_buf_size);
203204}
......@@ -210,7 +211,8 @@ void __sanitizer_symbolize_global(uptr data_addr, const char *fmt,
210211 DataInfo DI;
211212 if (!Symbolizer::GetOrInit()->SymbolizeData(data_addr, &DI)) return;
212213 InternalScopedString data_desc;
213 RenderData(&data_desc, fmt, &DI, common_flags()->strip_path_prefix);
214 StackTracePrinter::GetOrInit()->RenderData(&data_desc, fmt, &DI,
215 common_flags()->strip_path_prefix);
214216 internal_strncpy(out_buf, data_desc.data(), out_buf_size);
215217 out_buf[out_buf_size - 1] = 0;
216218}
lib/tsan/sanitizer_common/sanitizer_stacktrace_printer.cpp+81-52
......@@ -12,13 +12,28 @@
1212
1313#include "sanitizer_stacktrace_printer.h"
1414
15#include "sanitizer_common.h"
1516#include "sanitizer_file.h"
1617#include "sanitizer_flags.h"
1718#include "sanitizer_fuchsia.h"
19#include "sanitizer_symbolizer_markup.h"
1820
1921namespace __sanitizer {
2022
21const char *StripFunctionName(const char *function) {
23StackTracePrinter *StackTracePrinter::GetOrInit() {
24 static StackTracePrinter *stacktrace_printer;
25 static StaticSpinMutex init_mu;
26 SpinMutexLock l(&init_mu);
27 if (stacktrace_printer)
28 return stacktrace_printer;
29
30 stacktrace_printer = StackTracePrinter::NewStackTracePrinter();
31
32 CHECK(stacktrace_printer);
33 return stacktrace_printer;
34}
35
36const char *StackTracePrinter::StripFunctionName(const char *function) {
2237 if (!common_flags()->demangle)
2338 return function;
2439 if (!function)
......@@ -47,6 +62,13 @@ const char *StripFunctionName(const char *function) {
4762// sanitizer_symbolizer_markup.cpp implements these differently.
4863#if !SANITIZER_SYMBOLIZER_MARKUP
4964
65StackTracePrinter *StackTracePrinter::NewStackTracePrinter() {
66 if (common_flags()->enable_symbolizer_markup)
67 return new (GetGlobalLowLevelAllocator()) MarkupStackTracePrinter();
68
69 return new (GetGlobalLowLevelAllocator()) FormattedStackTracePrinter();
70}
71
5072static const char *DemangleFunctionName(const char *function) {
5173 if (!common_flags()->demangle)
5274 return function;
......@@ -130,20 +152,23 @@ static void MaybeBuildIdToBuffer(const AddressInfo &info, bool PrefixSpace,
130152 InternalScopedString *buffer) {
131153 if (info.uuid_size) {
132154 if (PrefixSpace)
133 buffer->append(" ");
134 buffer->append("(BuildId: ");
155 buffer->Append(" ");
156 buffer->Append("(BuildId: ");
135157 for (uptr i = 0; i < info.uuid_size; ++i) {
136 buffer->append("%02x", info.uuid[i]);
158 buffer->AppendF("%02x", info.uuid[i]);
137159 }
138 buffer->append(")");
160 buffer->Append(")");
139161 }
140162}
141163
142164static const char kDefaultFormat[] = " #%n %p %F %L";
143165
144void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
145 uptr address, const AddressInfo *info, bool vs_style,
146 const char *strip_path_prefix) {
166void FormattedStackTracePrinter::RenderFrame(InternalScopedString *buffer,
167 const char *format, int frame_no,
168 uptr address,
169 const AddressInfo *info,
170 bool vs_style,
171 const char *strip_path_prefix) {
147172 // info will be null in the case where symbolization is not needed for the
148173 // given format. This ensures that the code below will get a hard failure
149174 // rather than print incorrect information in case RenderNeedsSymbolization
......@@ -154,56 +179,56 @@ void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
154179 format = kDefaultFormat;
155180 for (const char *p = format; *p != '\0'; p++) {
156181 if (*p != '%') {
157 buffer->append("%c", *p);
182 buffer->AppendF("%c", *p);
158183 continue;
159184 }
160185 p++;
161186 switch (*p) {
162187 case '%':
163 buffer->append("%%");
188 buffer->Append("%");
164189 break;
165190 // Frame number and all fields of AddressInfo structure.
166191 case 'n':
167 buffer->append("%u", frame_no);
192 buffer->AppendF("%u", frame_no);
168193 break;
169194 case 'p':
170 buffer->append("0x%zx", address);
195 buffer->AppendF("%p", (void *)address);
171196 break;
172197 case 'm':
173 buffer->append("%s", StripPathPrefix(info->module, strip_path_prefix));
198 buffer->AppendF("%s", StripPathPrefix(info->module, strip_path_prefix));
174199 break;
175200 case 'o':
176 buffer->append("0x%zx", info->module_offset);
201 buffer->AppendF("0x%zx", info->module_offset);
177202 break;
178203 case 'b':
179204 MaybeBuildIdToBuffer(*info, /*PrefixSpace=*/false, buffer);
180205 break;
181206 case 'f':
182 buffer->append("%s",
183 DemangleFunctionName(StripFunctionName(info->function)));
207 buffer->AppendF("%s",
208 DemangleFunctionName(StripFunctionName(info->function)));
184209 break;
185210 case 'q':
186 buffer->append("0x%zx", info->function_offset != AddressInfo::kUnknown
187 ? info->function_offset
188 : 0x0);
211 buffer->AppendF("0x%zx", info->function_offset != AddressInfo::kUnknown
212 ? info->function_offset
213 : 0x0);
189214 break;
190215 case 's':
191 buffer->append("%s", StripPathPrefix(info->file, strip_path_prefix));
216 buffer->AppendF("%s", StripPathPrefix(info->file, strip_path_prefix));
192217 break;
193218 case 'l':
194 buffer->append("%d", info->line);
219 buffer->AppendF("%d", info->line);
195220 break;
196221 case 'c':
197 buffer->append("%d", info->column);
222 buffer->AppendF("%d", info->column);
198223 break;
199224 // Smarter special cases.
200225 case 'F':
201226 // Function name and offset, if file is unknown.
202227 if (info->function) {
203 buffer->append("in %s",
204 DemangleFunctionName(StripFunctionName(info->function)));
228 buffer->AppendF(
229 "in %s", DemangleFunctionName(StripFunctionName(info->function)));
205230 if (!info->file && info->function_offset != AddressInfo::kUnknown)
206 buffer->append("+0x%zx", info->function_offset);
231 buffer->AppendF("+0x%zx", info->function_offset);
207232 }
208233 break;
209234 case 'S':
......@@ -224,7 +249,7 @@ void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
224249 MaybeBuildIdToBuffer(*info, /*PrefixSpace=*/true, buffer);
225250#endif
226251 } else {
227 buffer->append("(<unknown module>)");
252 buffer->Append("(<unknown module>)");
228253 }
229254 break;
230255 case 'M':
......@@ -239,18 +264,18 @@ void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
239264 MaybeBuildIdToBuffer(*info, /*PrefixSpace=*/true, buffer);
240265#endif
241266 } else {
242 buffer->append("(%p)", (void *)address);
267 buffer->AppendF("(%p)", (void *)address);
243268 }
244269 break;
245270 default:
246271 Report("Unsupported specifier in stack frame format: %c (%p)!\n", *p,
247 (void *)p);
272 (const void *)p);
248273 Die();
249274 }
250275 }
251276}
252277
253bool RenderNeedsSymbolization(const char *format) {
278bool FormattedStackTracePrinter::RenderNeedsSymbolization(const char *format) {
254279 if (0 == internal_strcmp(format, "DEFAULT"))
255280 format = kDefaultFormat;
256281 for (const char *p = format; *p != '\0'; p++) {
......@@ -273,30 +298,32 @@ bool RenderNeedsSymbolization(const char *format) {
273298 return false;
274299}
275300
276void RenderData(InternalScopedString *buffer, const char *format,
277 const DataInfo *DI, const char *strip_path_prefix) {
301void FormattedStackTracePrinter::RenderData(InternalScopedString *buffer,
302 const char *format,
303 const DataInfo *DI,
304 const char *strip_path_prefix) {
278305 for (const char *p = format; *p != '\0'; p++) {
279306 if (*p != '%') {
280 buffer->append("%c", *p);
307 buffer->AppendF("%c", *p);
281308 continue;
282309 }
283310 p++;
284311 switch (*p) {
285312 case '%':
286 buffer->append("%%");
313 buffer->Append("%");
287314 break;
288315 case 's':
289 buffer->append("%s", StripPathPrefix(DI->file, strip_path_prefix));
316 buffer->AppendF("%s", StripPathPrefix(DI->file, strip_path_prefix));
290317 break;
291318 case 'l':
292 buffer->append("%zu", DI->line);
319 buffer->AppendF("%zu", DI->line);
293320 break;
294321 case 'g':
295 buffer->append("%s", DI->name);
322 buffer->AppendF("%s", DI->name);
296323 break;
297324 default:
298325 Report("Unsupported specifier in stack frame format: %c (%p)!\n", *p,
299 (void *)p);
326 (const void *)p);
300327 Die();
301328 }
302329 }
......@@ -304,33 +331,35 @@ void RenderData(InternalScopedString *buffer, const char *format,
304331
305332#endif // !SANITIZER_SYMBOLIZER_MARKUP
306333
307void RenderSourceLocation(InternalScopedString *buffer, const char *file,
308 int line, int column, bool vs_style,
309 const char *strip_path_prefix) {
334void StackTracePrinter::RenderSourceLocation(InternalScopedString *buffer,
335 const char *file, int line,
336 int column, bool vs_style,
337 const char *strip_path_prefix) {
310338 if (vs_style && line > 0) {
311 buffer->append("%s(%d", StripPathPrefix(file, strip_path_prefix), line);
339 buffer->AppendF("%s(%d", StripPathPrefix(file, strip_path_prefix), line);
312340 if (column > 0)
313 buffer->append(",%d", column);
314 buffer->append(")");
341 buffer->AppendF(",%d", column);
342 buffer->Append(")");
315343 return;
316344 }
317345
318 buffer->append("%s", StripPathPrefix(file, strip_path_prefix));
346 buffer->AppendF("%s", StripPathPrefix(file, strip_path_prefix));
319347 if (line > 0) {
320 buffer->append(":%d", line);
348 buffer->AppendF(":%d", line);
321349 if (column > 0)
322 buffer->append(":%d", column);
350 buffer->AppendF(":%d", column);
323351 }
324352}
325353
326void RenderModuleLocation(InternalScopedString *buffer, const char *module,
327 uptr offset, ModuleArch arch,
328 const char *strip_path_prefix) {
329 buffer->append("(%s", StripPathPrefix(module, strip_path_prefix));
354void StackTracePrinter::RenderModuleLocation(InternalScopedString *buffer,
355 const char *module, uptr offset,
356 ModuleArch arch,
357 const char *strip_path_prefix) {
358 buffer->AppendF("(%s", StripPathPrefix(module, strip_path_prefix));
330359 if (arch != kModuleArchUnknown) {
331 buffer->append(":%s", ModuleArchToString(arch));
360 buffer->AppendF(":%s", ModuleArchToString(arch));
332361 }
333 buffer->append("+0x%zx)", offset);
362 buffer->AppendF("+0x%zx)", offset);
334363}
335364
336365} // namespace __sanitizer
lib/tsan/sanitizer_common/sanitizer_stacktrace_printer.h+92-51
......@@ -13,61 +13,102 @@
1313#define SANITIZER_STACKTRACE_PRINTER_H
1414
1515#include "sanitizer_common.h"
16#include "sanitizer_internal_defs.h"
1617#include "sanitizer_symbolizer.h"
1718
1819namespace __sanitizer {
1920
20// Strip interceptor prefixes from function name.
21const char *StripFunctionName(const char *function);
22
23// Render the contents of "info" structure, which represents the contents of
24// stack frame "frame_no" and appends it to the "buffer". "format" is a
25// string with placeholders, which is copied to the output with
26// placeholders substituted with the contents of "info". For example,
27// format string
28// " frame %n: function %F at %S"
29// will be turned into
30// " frame 10: function foo::bar() at my/file.cc:10"
31// You may additionally pass "strip_path_prefix" to strip prefixes of paths to
32// source files and modules.
33// Here's the full list of available placeholders:
34// %% - represents a '%' character;
35// %n - frame number (copy of frame_no);
36// %p - PC in hex format;
37// %m - path to module (binary or shared object);
38// %o - offset in the module in hex format;
39// %f - function name;
40// %q - offset in the function in hex format (*if available*);
41// %s - path to source file;
42// %l - line in the source file;
43// %c - column in the source file;
44// %F - if function is known to be <foo>, prints "in <foo>", possibly
45// followed by the offset in this function, but only if source file
46// is unknown;
47// %S - prints file/line/column information;
48// %L - prints location information: file/line/column, if it is known, or
49// module+offset if it is known, or (<unknown module>) string.
50// %M - prints module basename and offset, if it is known, or PC.
51void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
52 uptr address, const AddressInfo *info, bool vs_style,
53 const char *strip_path_prefix = "");
54
55bool RenderNeedsSymbolization(const char *format);
56
57void RenderSourceLocation(InternalScopedString *buffer, const char *file,
58 int line, int column, bool vs_style,
59 const char *strip_path_prefix);
60
61void RenderModuleLocation(InternalScopedString *buffer, const char *module,
62 uptr offset, ModuleArch arch,
63 const char *strip_path_prefix);
64
65// Same as RenderFrame, but for data section (global variables).
66// Accepts %s, %l from above.
67// Also accepts:
68// %g - name of the global variable.
69void RenderData(InternalScopedString *buffer, const char *format,
70 const DataInfo *DI, const char *strip_path_prefix = "");
21// StacktracePrinter is an interface that is implemented by
22// classes that can perform rendering of the different parts
23// of a stacktrace.
24class StackTracePrinter {
25 public:
26 static StackTracePrinter *GetOrInit();
27
28 // Strip interceptor prefixes from function name.
29 const char *StripFunctionName(const char *function);
30
31 virtual void RenderFrame(InternalScopedString *buffer, const char *format,
32 int frame_no, uptr address, const AddressInfo *info,
33 bool vs_style, const char *strip_path_prefix = "") {
34 // Should be pure virtual, but we can't depend on __cxa_pure_virtual.
35 UNIMPLEMENTED();
36 }
37
38 virtual bool RenderNeedsSymbolization(const char *format) {
39 // Should be pure virtual, but we can't depend on __cxa_pure_virtual.
40 UNIMPLEMENTED();
41 }
42
43 void RenderSourceLocation(InternalScopedString *buffer, const char *file,
44 int line, int column, bool vs_style,
45 const char *strip_path_prefix);
46
47 void RenderModuleLocation(InternalScopedString *buffer, const char *module,
48 uptr offset, ModuleArch arch,
49 const char *strip_path_prefix);
50 virtual void RenderData(InternalScopedString *buffer, const char *format,
51 const DataInfo *DI,
52 const char *strip_path_prefix = "") {
53 // Should be pure virtual, but we can't depend on __cxa_pure_virtual.
54 UNIMPLEMENTED();
55 }
56
57 private:
58 // To be called from StackTracePrinter::GetOrInit
59 static StackTracePrinter *NewStackTracePrinter();
60
61 protected:
62 ~StackTracePrinter() {}
63};
64
65class FormattedStackTracePrinter : public StackTracePrinter {
66 public:
67 // Render the contents of "info" structure, which represents the contents of
68 // stack frame "frame_no" and appends it to the "buffer". "format" is a
69 // string with placeholders, which is copied to the output with
70 // placeholders substituted with the contents of "info". For example,
71 // format string
72 // " frame %n: function %F at %S"
73 // will be turned into
74 // " frame 10: function foo::bar() at my/file.cc:10"
75 // You may additionally pass "strip_path_prefix" to strip prefixes of paths to
76 // source files and modules.
77 // Here's the full list of available placeholders:
78 // %% - represents a '%' character;
79 // %n - frame number (copy of frame_no);
80 // %p - PC in hex format;
81 // %m - path to module (binary or shared object);
82 // %o - offset in the module in hex format;
83 // %f - function name;
84 // %q - offset in the function in hex format (*if available*);
85 // %s - path to source file;
86 // %l - line in the source file;
87 // %c - column in the source file;
88 // %F - if function is known to be <foo>, prints "in <foo>", possibly
89 // followed by the offset in this function, but only if source file
90 // is unknown;
91 // %S - prints file/line/column information;
92 // %L - prints location information: file/line/column, if it is known, or
93 // module+offset if it is known, or (<unknown module>) string.
94 // %M - prints module basename and offset, if it is known, or PC.
95 void RenderFrame(InternalScopedString *buffer, const char *format,
96 int frame_no, uptr address, const AddressInfo *info,
97 bool vs_style, const char *strip_path_prefix = "") override;
98
99 bool RenderNeedsSymbolization(const char *format) override;
100
101 // Same as RenderFrame, but for data section (global variables).
102 // Accepts %s, %l from above.
103 // Also accepts:
104 // %g - name of the global variable.
105 void RenderData(InternalScopedString *buffer, const char *format,
106 const DataInfo *DI,
107 const char *strip_path_prefix = "") override;
108
109 protected:
110 ~FormattedStackTracePrinter() {}
111};
71112
72113} // namespace __sanitizer
73114
lib/tsan/sanitizer_common/sanitizer_stacktrace_sparc.cpp+5-6
......@@ -58,17 +58,16 @@ void BufferedStackTrace::UnwindFast(uptr pc, uptr bp, uptr stack_top,
5858 // Avoid infinite loop when frame == frame[0] by using frame > prev_frame.
5959 while (IsValidFrame(bp, stack_top, bottom) && IsAligned(bp, sizeof(uhwptr)) &&
6060 size < max_depth) {
61 uhwptr pc1 = ((uhwptr *)bp)[15];
61 // %o7 contains the address of the call instruction and not the
62 // return address, so we need to compensate.
63 uhwptr pc1 = GetNextInstructionPc(((uhwptr *)bp)[15]);
6264 // Let's assume that any pointer in the 0th page is invalid and
6365 // stop unwinding here. If we're adding support for a platform
6466 // where this isn't true, we need to reconsider this check.
6567 if (pc1 < kPageSize)
6668 break;
67 if (pc1 != pc) {
68 // %o7 contains the address of the call instruction and not the
69 // return address, so we need to compensate.
70 trace_buffer[size++] = GetNextInstructionPc((uptr)pc1);
71 }
69 if (pc1 != pc)
70 trace_buffer[size++] = pc1;
7271 bottom = bp;
7372 bp = (uptr)((uhwptr *)bp)[14] + STACK_BIAS;
7473 }
lib/tsan/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp+5-5
......@@ -257,8 +257,8 @@ static void TracerThreadDieCallback() {
257257static void TracerThreadSignalHandler(int signum, __sanitizer_siginfo *siginfo,
258258 void *uctx) {
259259 SignalContext ctx(siginfo, uctx);
260 Printf("Tracer caught signal %d: addr=0x%zx pc=0x%zx sp=0x%zx\n", signum,
261 ctx.addr, ctx.pc, ctx.sp);
260 Printf("Tracer caught signal %d: addr=%p pc=%p sp=%p\n", signum,
261 (void *)ctx.addr, (void *)ctx.pc, (void *)ctx.sp);
262262 ThreadSuspender *inst = thread_suspender_instance;
263263 if (inst) {
264264 if (signum == SIGABRT)
......@@ -565,7 +565,7 @@ PtraceRegistersStatus SuspendedThreadsListLinux::GetRegistersAndSP(
565565 constexpr uptr uptr_sz = sizeof(uptr);
566566 int pterrno;
567567#ifdef ARCH_IOVEC_FOR_GETREGSET
568 auto append = [&](uptr regset) {
568 auto AppendF = [&](uptr regset) {
569569 uptr size = buffer->size();
570570 // NT_X86_XSTATE requires 64bit alignment.
571571 uptr size_up = RoundUpTo(size, 8 / uptr_sz);
......@@ -596,11 +596,11 @@ PtraceRegistersStatus SuspendedThreadsListLinux::GetRegistersAndSP(
596596 };
597597
598598 buffer->clear();
599 bool fail = !append(NT_PRSTATUS);
599 bool fail = !AppendF(NT_PRSTATUS);
600600 if (!fail) {
601601 // Accept the first available and do not report errors.
602602 for (uptr regs : kExtraRegs)
603 if (regs && append(regs))
603 if (regs && AppendF(regs))
604604 break;
605605 }
606606#else
lib/tsan/sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp+2-2
......@@ -158,8 +158,8 @@ static void TracerThreadDieCallback() {
158158static void TracerThreadSignalHandler(int signum, __sanitizer_siginfo *siginfo,
159159 void *uctx) {
160160 SignalContext ctx(siginfo, uctx);
161 Printf("Tracer caught signal %d: addr=0x%zx pc=0x%zx sp=0x%zx\n", signum,
162 ctx.addr, ctx.pc, ctx.sp);
161 Printf("Tracer caught signal %d: addr=%p pc=%p sp=%p\n", signum,
162 (void *)ctx.addr, (void *)ctx.pc, (void *)ctx.sp);
163163 ThreadSuspender *inst = thread_suspender_instance;
164164 if (inst) {
165165 if (signum == SIGABRT)
lib/tsan/sanitizer_common/sanitizer_suppressions.cpp+5-2
......@@ -86,7 +86,7 @@ void SuppressionContext::ParseFromFile(const char *filename) {
8686 }
8787
8888 Parse(file_contents);
89 UnmapOrDie(file_contents, contents_size);
89 UnmapOrDie(file_contents, buffer_size);
9090}
9191
9292bool SuppressionContext::Match(const char *str, const char *type,
......@@ -138,7 +138,10 @@ void SuppressionContext::Parse(const char *str) {
138138 }
139139 }
140140 if (type == suppression_types_num_) {
141 Printf("%s: failed to parse suppressions\n", SanitizerToolName);
141 Printf("%s: failed to parse suppressions.\n", SanitizerToolName);
142 Printf("Supported suppression types are:\n");
143 for (type = 0; type < suppression_types_num_; type++)
144 Printf("- %s\n", suppression_types_[type]);
142145 Die();
143146 }
144147 Suppression s;
lib/tsan/sanitizer_common/sanitizer_symbolizer.cpp+4-1
......@@ -10,6 +10,8 @@
1010// run-time libraries.
1111//===----------------------------------------------------------------------===//
1212
13#include <errno.h>
14
1315#include "sanitizer_allocator_internal.h"
1416#include "sanitizer_common.h"
1517#include "sanitizer_internal_defs.h"
......@@ -128,7 +130,7 @@ Symbolizer::Symbolizer(IntrusiveList<SymbolizerTool> tools)
128130 start_hook_(0), end_hook_(0) {}
129131
130132Symbolizer::SymbolizerScope::SymbolizerScope(const Symbolizer *sym)
131 : sym_(sym) {
133 : sym_(sym), errno_(errno) {
132134 if (sym_->start_hook_)
133135 sym_->start_hook_();
134136}
......@@ -136,6 +138,7 @@ Symbolizer::SymbolizerScope::SymbolizerScope(const Symbolizer *sym)
136138Symbolizer::SymbolizerScope::~SymbolizerScope() {
137139 if (sym_->end_hook_)
138140 sym_->end_hook_();
141 errno = errno_;
139142}
140143
141144} // namespace __sanitizer
lib/tsan/sanitizer_common/sanitizer_symbolizer.h+25-2
......@@ -64,6 +64,26 @@ struct SymbolizedStack {
6464 SymbolizedStack();
6565};
6666
67class SymbolizedStackHolder {
68 SymbolizedStack *Stack;
69
70 void clear() {
71 if (Stack)
72 Stack->ClearAll();
73 }
74
75 public:
76 explicit SymbolizedStackHolder(SymbolizedStack *Stack = nullptr)
77 : Stack(Stack) {}
78 ~SymbolizedStackHolder() { clear(); }
79 void reset(SymbolizedStack *S = nullptr) {
80 if (Stack != S)
81 clear();
82 Stack = S;
83 }
84 const SymbolizedStack *get() const { return Stack; }
85};
86
6787// For now, DataInfo is used to describe global variable.
6888struct DataInfo {
6989 // Owns all the string members. Storage for them is
......@@ -136,7 +156,7 @@ class Symbolizer final {
136156
137157 // Release internal caches (if any).
138158 void Flush();
139 // Attempts to demangle the provided C++ mangled name.
159 // Attempts to demangle the provided C++ mangled name. Never returns nullptr.
140160 const char *Demangle(const char *name);
141161
142162 // Allow user to install hooks that would be called before/after Symbolizer
......@@ -154,6 +174,8 @@ class Symbolizer final {
154174
155175 void InvalidateModuleList();
156176
177 const ListOfModules &GetRefreshedListOfModules();
178
157179 private:
158180 // GetModuleNameAndOffsetForPC has to return a string to the caller.
159181 // Since the corresponding module might get unloaded later, we should create
......@@ -187,7 +209,7 @@ class Symbolizer final {
187209 // If stale, need to reload the modules before looking up addresses.
188210 bool modules_fresh_;
189211
190 // Platform-specific default demangler, must not return nullptr.
212 // Platform-specific default demangler, returns nullptr on failure.
191213 const char *PlatformDemangle(const char *name);
192214
193215 static Symbolizer *symbolizer_;
......@@ -212,6 +234,7 @@ class Symbolizer final {
212234 ~SymbolizerScope();
213235 private:
214236 const Symbolizer *sym_;
237 int errno_; // Backup errno in case symbolizer change the value.
215238 };
216239};
217240
lib/tsan/sanitizer_common/sanitizer_symbolizer_fuchsia.h deleted-42
......@@ -1,42 +0,0 @@
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+9
......@@ -160,6 +160,15 @@ void ParseSymbolizePCOutput(const char *str, SymbolizedStack *res);
160160// Used by LLVMSymbolizer and InternalSymbolizer.
161161void ParseSymbolizeDataOutput(const char *str, DataInfo *info);
162162
163// Parses repeated strings in the following format:
164// <function_name>
165// <var_name>
166// <file_name>:<line_number>[:<column_number>]
167// [<frame_offset>|??] [<size>|??] [<tag_offset>|??]
168// Used by LLVMSymbolizer and InternalSymbolizer.
169void ParseSymbolizeFrameOutput(const char *str,
170 InternalMmapVector<LocalInfo> *locals);
171
163172} // namespace __sanitizer
164173
165174#endif // SANITIZER_SYMBOLIZER_INTERNAL_H
lib/tsan/sanitizer_common/sanitizer_symbolizer_libbacktrace.cpp+1-1
......@@ -199,7 +199,7 @@ static char *DemangleAlloc(const char *name, bool always_alloc) {
199199#endif
200200 if (always_alloc)
201201 return internal_strdup(name);
202 return 0;
202 return nullptr;
203203}
204204
205205const char *LibbacktraceSymbolizer::Demangle(const char *name) {
lib/tsan/sanitizer_common/sanitizer_symbolizer_libcdep.cpp+15-5
......@@ -117,7 +117,7 @@ bool Symbolizer::SymbolizeData(uptr addr, DataInfo *info) {
117117 return true;
118118 }
119119 }
120 return true;
120 return false;
121121}
122122
123123bool Symbolizer::SymbolizeFrame(uptr addr, FrameInfo *info) {
......@@ -133,7 +133,7 @@ bool Symbolizer::SymbolizeFrame(uptr addr, FrameInfo *info) {
133133 return true;
134134 }
135135 }
136 return true;
136 return false;
137137}
138138
139139bool Symbolizer::GetModuleNameAndOffsetForPC(uptr pc, const char **module_name,
......@@ -159,13 +159,16 @@ void Symbolizer::Flush() {
159159}
160160
161161const char *Symbolizer::Demangle(const char *name) {
162 CHECK(name);
162163 Lock l(&mu_);
163164 for (auto &tool : tools_) {
164165 SymbolizerScope sym_scope(this);
165166 if (const char *demangled = tool.Demangle(name))
166167 return demangled;
167168 }
168 return PlatformDemangle(name);
169 if (const char *demangled = PlatformDemangle(name))
170 return demangled;
171 return name;
169172}
170173
171174bool Symbolizer::FindModuleNameAndOffsetForAddress(uptr address,
......@@ -188,6 +191,13 @@ void Symbolizer::RefreshModules() {
188191 modules_fresh_ = true;
189192}
190193
194const ListOfModules &Symbolizer::GetRefreshedListOfModules() {
195 if (!modules_fresh_)
196 RefreshModules();
197
198 return modules_;
199}
200
191201static const LoadedModule *SearchForModule(const ListOfModules &modules,
192202 uptr address) {
193203 for (uptr i = 0; i < modules.size(); i++) {
......@@ -382,8 +392,8 @@ void ParseSymbolizeDataOutput(const char *str, DataInfo *info) {
382392 str = ExtractUptr(str, "\n", &info->line);
383393}
384394
385static void ParseSymbolizeFrameOutput(const char *str,
386 InternalMmapVector<LocalInfo> *locals) {
395void ParseSymbolizeFrameOutput(const char *str,
396 InternalMmapVector<LocalInfo> *locals) {
387397 if (internal_strncmp(str, "??", 2) == 0)
388398 return;
389399
lib/tsan/sanitizer_common/sanitizer_symbolizer_mac.cpp+4-1
......@@ -42,7 +42,8 @@ bool DlAddrSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) {
4242 }
4343
4444 const char *demangled = DemangleSwiftAndCXX(info.dli_sname);
45 if (!demangled) return false;
45 if (!demangled)
46 demangled = info.dli_sname;
4647 stack->info.function = internal_strdup(demangled);
4748 return true;
4849}
......@@ -52,6 +53,8 @@ bool DlAddrSymbolizer::SymbolizeData(uptr addr, DataInfo *datainfo) {
5253 int result = dladdr((const void *)addr, &info);
5354 if (!result) return false;
5455 const char *demangled = DemangleSwiftAndCXX(info.dli_sname);
56 if (!demangled)
57 demangled = info.dli_sname;
5558 datainfo->name = internal_strdup(demangled);
5659 datainfo->start = (uptr)info.dli_saddr;
5760 return true;
lib/tsan/sanitizer_common/sanitizer_symbolizer_markup.cpp+120-108
......@@ -8,143 +8,155 @@
88//
99// This file is shared between various sanitizers' runtime libraries.
1010//
11// Implementation of offline markup symbolizer.
11// This generic support for offline symbolizing is based on the
12// Fuchsia port. We don't do any actual symbolization per se.
13// Instead, we emit text containing raw addresses and raw linkage
14// symbol names, embedded in Fuchsia's symbolization markup format.
15// See the spec at:
16// https://llvm.org/docs/SymbolizerMarkupFormat.html
1217//===----------------------------------------------------------------------===//
1318
14#include "sanitizer_platform.h"
15#if SANITIZER_SYMBOLIZER_MARKUP
16
17#if SANITIZER_FUCHSIA
18#include "sanitizer_symbolizer_fuchsia.h"
19# endif
19#include "sanitizer_symbolizer_markup.h"
2020
21# include <limits.h>
22# include <unwind.h>
23
24# include "sanitizer_stacktrace.h"
25# include "sanitizer_symbolizer.h"
21#include "sanitizer_common.h"
22#include "sanitizer_symbolizer.h"
23#include "sanitizer_symbolizer_markup_constants.h"
2624
2725namespace __sanitizer {
2826
29// This generic support for offline symbolizing is based on the
30// Fuchsia port. We don't do any actual symbolization per se.
31// Instead, we emit text containing raw addresses and raw linkage
32// symbol names, embedded in Fuchsia's symbolization markup format.
33// Fuchsia's logging infrastructure emits enough information about
34// process memory layout that a post-processing filter can do the
35// symbolization and pretty-print the markup. See the spec at:
36// https://fuchsia.googlesource.com/zircon/+/master/docs/symbolizer_markup.md
37
38// This is used by UBSan for type names, and by ASan for global variable names.
39// It's expected to return a static buffer that will be reused on each call.
40const char *Symbolizer::Demangle(const char *name) {
41 static char buffer[kFormatDemangleMax];
42 internal_snprintf(buffer, sizeof(buffer), kFormatDemangle, name);
43 return buffer;
27void MarkupStackTracePrinter::RenderData(InternalScopedString *buffer,
28 const char *format, const DataInfo *DI,
29 const char *strip_path_prefix) {
30 RenderContext(buffer);
31 buffer->AppendF(kFormatData, reinterpret_cast<void *>(DI->start));
4432}
4533
46// This is used mostly for suppression matching. Making it work
47// would enable "interceptor_via_lib" suppressions. It's also used
48// once in UBSan to say "in module ..." in a message that also
49// includes an address in the module, so post-processing can already
50// pretty-print that so as to indicate the module.
51bool Symbolizer::GetModuleNameAndOffsetForPC(uptr pc, const char **module_name,
52 uptr *module_address) {
34bool MarkupStackTracePrinter::RenderNeedsSymbolization(const char *format) {
5335 return false;
5436}
5537
56// This is mainly used by hwasan for online symbolization. This isn't needed
57// since hwasan can always just dump stack frames for offline symbolization.
58bool Symbolizer::SymbolizeFrame(uptr addr, FrameInfo *info) { return false; }
59
60// This is used in some places for suppression checking, which we
61// don't really support for Fuchsia. It's also used in UBSan to
62// identify a PC location to a function name, so we always fill in
63// the function member with a string containing markup around the PC
64// value.
65// TODO(mcgrathr): Under SANITIZER_GO, it's currently used by TSan
66// to render stack frames, but that should be changed to use
67// RenderStackFrame.
68SymbolizedStack *Symbolizer::SymbolizePC(uptr addr) {
69 SymbolizedStack *s = SymbolizedStack::New(addr);
38// We don't support the stack_trace_format flag at all.
39void MarkupStackTracePrinter::RenderFrame(InternalScopedString *buffer,
40 const char *format, int frame_no,
41 uptr address, const AddressInfo *info,
42 bool vs_style,
43 const char *strip_path_prefix) {
44 CHECK(!RenderNeedsSymbolization(format));
45 RenderContext(buffer);
46 buffer->AppendF(kFormatFrame, frame_no, reinterpret_cast<void *>(address));
47}
48
49bool MarkupSymbolizerTool::SymbolizePC(uptr addr, SymbolizedStack *stack) {
7050 char buffer[kFormatFunctionMax];
71 internal_snprintf(buffer, sizeof(buffer), kFormatFunction, addr);
72 s->info.function = internal_strdup(buffer);
73 return s;
51 internal_snprintf(buffer, sizeof(buffer), kFormatFunction,
52 reinterpret_cast<void *>(addr));
53 stack->info.function = internal_strdup(buffer);
54 return true;
7455}
7556
76// Always claim we succeeded, so that RenderDataInfo will be called.
77bool Symbolizer::SymbolizeData(uptr addr, DataInfo *info) {
57bool MarkupSymbolizerTool::SymbolizeData(uptr addr, DataInfo *info) {
7858 info->Clear();
7959 info->start = addr;
8060 return true;
8161}
8262
83// We ignore the format argument to __sanitizer_symbolize_global.
84void RenderData(InternalScopedString *buffer, const char *format,
85 const DataInfo *DI, const char *strip_path_prefix) {
86 buffer->append(kFormatData, DI->start);
63const char *MarkupSymbolizerTool::Demangle(const char *name) {
64 static char buffer[kFormatDemangleMax];
65 internal_snprintf(buffer, sizeof(buffer), kFormatDemangle, name);
66 return buffer;
8767}
8868
89bool RenderNeedsSymbolization(const char *format) { return false; }
90
91// We don't support the stack_trace_format flag at all.
92void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
93 uptr address, const AddressInfo *info, bool vs_style,
94 const char *strip_path_prefix) {
95 CHECK(!RenderNeedsSymbolization(format));
96 buffer->append(kFormatFrame, frame_no, address);
69// Fuchsia's implementation of symbolizer markup doesn't need to emit contextual
70// elements at this point.
71// Fuchsia's logging infrastructure emits enough information about
72// process memory layout that a post-processing filter can do the
73// symbolization and pretty-print the markup.
74#if !SANITIZER_FUCHSIA
75
76static bool ModulesEq(const LoadedModule &module,
77 const RenderedModule &renderedModule) {
78 return module.base_address() == renderedModule.base_address &&
79 internal_memcmp(module.uuid(), renderedModule.uuid,
80 module.uuid_size()) == 0 &&
81 internal_strcmp(module.full_name(), renderedModule.full_name) == 0;
9782}
9883
99Symbolizer *Symbolizer::PlatformInit() {
100 return new (symbolizer_allocator_) Symbolizer({});
84static bool ModuleHasBeenRendered(
85 const LoadedModule &module,
86 const InternalMmapVectorNoCtor<RenderedModule> &renderedModules) {
87 for (const auto &renderedModule : renderedModules)
88 if (ModulesEq(module, renderedModule))
89 return true;
90
91 return false;
10192}
10293
103void Symbolizer::LateInitialize() { Symbolizer::GetOrInit(); }
104
105void StartReportDeadlySignal() {}
106void ReportDeadlySignal(const SignalContext &sig, u32 tid,
107 UnwindSignalStackCallbackType unwind,
108 const void *unwind_context) {}
109
110#if SANITIZER_CAN_SLOW_UNWIND
111struct UnwindTraceArg {
112 BufferedStackTrace *stack;
113 u32 max_depth;
114};
115
116_Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) {
117 UnwindTraceArg *arg = static_cast<UnwindTraceArg *>(param);
118 CHECK_LT(arg->stack->size, arg->max_depth);
119 uptr pc = _Unwind_GetIP(ctx);
120 if (pc < PAGE_SIZE) return _URC_NORMAL_STOP;
121 arg->stack->trace_buffer[arg->stack->size++] = pc;
122 return (arg->stack->size == arg->max_depth ? _URC_NORMAL_STOP
123 : _URC_NO_REASON);
94static void RenderModule(InternalScopedString *buffer,
95 const LoadedModule &module, uptr moduleId) {
96 InternalScopedString buildIdBuffer;
97 for (uptr i = 0; i < module.uuid_size(); i++)
98 buildIdBuffer.AppendF("%02x", module.uuid()[i]);
99
100 buffer->AppendF(kFormatModule, moduleId, module.full_name(),
101 buildIdBuffer.data());
102 buffer->Append("\n");
124103}
125104
126void BufferedStackTrace::UnwindSlow(uptr pc, u32 max_depth) {
127 CHECK_GE(max_depth, 2);
128 size = 0;
129 UnwindTraceArg arg = {this, Min(max_depth + 1, kStackTraceMax)};
130 _Unwind_Backtrace(Unwind_Trace, &arg);
131 CHECK_GT(size, 0);
132 // We need to pop a few frames so that pc is on top.
133 uptr to_pop = LocatePcInTrace(pc);
134 // trace_buffer[0] belongs to the current function so we always pop it,
135 // unless there is only 1 frame in the stack trace (1 frame is always better
136 // than 0!).
137 PopStackFrames(Min(to_pop, static_cast<uptr>(1)));
138 trace_buffer[0] = pc;
105static void RenderMmaps(InternalScopedString *buffer,
106 const LoadedModule &module, uptr moduleId) {
107 InternalScopedString accessBuffer;
108
109 // All module mmaps are readable at least
110 for (const auto &range : module.ranges()) {
111 accessBuffer.Append("r");
112 if (range.writable)
113 accessBuffer.Append("w");
114 if (range.executable)
115 accessBuffer.Append("x");
116
117 //{{{mmap:%starting_addr:%size_in_hex:load:%moduleId:r%(w|x):%relative_addr}}}
118
119 // module.base_address == dlpi_addr
120 // range.beg == dlpi_addr + p_vaddr
121 // relative address == p_vaddr == range.beg - module.base_address
122 buffer->AppendF(kFormatMmap, reinterpret_cast<void *>(range.beg),
123 range.end - range.beg, static_cast<int>(moduleId),
124 accessBuffer.data(), range.beg - module.base_address());
125
126 buffer->Append("\n");
127 accessBuffer.clear();
128 }
139129}
140130
141void BufferedStackTrace::UnwindSlow(uptr pc, void *context, u32 max_depth) {
142 CHECK(context);
143 CHECK_GE(max_depth, 2);
144 UNREACHABLE("signal context doesn't exist");
131void MarkupStackTracePrinter::RenderContext(InternalScopedString *buffer) {
132 if (renderedModules_.size() == 0)
133 buffer->Append("{{{reset}}}\n");
134
135 const auto &modules = Symbolizer::GetOrInit()->GetRefreshedListOfModules();
136
137 for (const auto &module : modules) {
138 if (ModuleHasBeenRendered(module, renderedModules_))
139 continue;
140
141 // symbolizer markup id, used to refer to this modules from other contextual
142 // elements
143 uptr moduleId = renderedModules_.size();
144
145 RenderModule(buffer, module, moduleId);
146 RenderMmaps(buffer, module, moduleId);
147
148 renderedModules_.push_back({
149 internal_strdup(module.full_name()),
150 module.base_address(),
151 {},
152 });
153
154 // kModuleUUIDSize is the size of curModule.uuid
155 CHECK_GE(kModuleUUIDSize, module.uuid_size());
156 internal_memcpy(renderedModules_.back().uuid, module.uuid(),
157 module.uuid_size());
158 }
145159}
146#endif // SANITIZER_CAN_SLOW_UNWIND
160#endif // !SANITIZER_FUCHSIA
147161
148162} // namespace __sanitizer
149
150#endif // SANITIZER_SYMBOLIZER_MARKUP
lib/tsan/sanitizer_common/sanitizer_symbolizer_markup.h created+79
......@@ -0,0 +1,79 @@
1//===-- sanitizer_symbolizer_markup.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// Header for the offline markup symbolizer.
12//===----------------------------------------------------------------------===//
13#ifndef SANITIZER_SYMBOLIZER_MARKUP_H
14#define SANITIZER_SYMBOLIZER_MARKUP_H
15
16#include "sanitizer_common.h"
17#include "sanitizer_stacktrace_printer.h"
18#include "sanitizer_symbolizer.h"
19#include "sanitizer_symbolizer_internal.h"
20
21namespace __sanitizer {
22
23// Simplier view of a LoadedModule. It only holds information necessary to
24// identify unique modules.
25struct RenderedModule {
26 char *full_name;
27 uptr base_address;
28 u8 uuid[kModuleUUIDSize]; // BuildId
29};
30
31class MarkupStackTracePrinter : public StackTracePrinter {
32 public:
33 // We don't support the stack_trace_format flag at all.
34 void RenderFrame(InternalScopedString *buffer, const char *format,
35 int frame_no, uptr address, const AddressInfo *info,
36 bool vs_style, const char *strip_path_prefix = "") override;
37
38 bool RenderNeedsSymbolization(const char *format) override;
39
40 // We ignore the format argument to __sanitizer_symbolize_global.
41 void RenderData(InternalScopedString *buffer, const char *format,
42 const DataInfo *DI,
43 const char *strip_path_prefix = "") override;
44
45 private:
46 // Keeps track of the modules that have been rendered to avoid re-rendering
47 // them
48 InternalMmapVector<RenderedModule> renderedModules_;
49 void RenderContext(InternalScopedString *buffer);
50
51 protected:
52 ~MarkupStackTracePrinter() {}
53};
54
55class MarkupSymbolizerTool final : public SymbolizerTool {
56 public:
57 // This is used in some places for suppression checking, which we
58 // don't really support for Fuchsia. It's also used in UBSan to
59 // identify a PC location to a function name, so we always fill in
60 // the function member with a string containing markup around the PC
61 // value.
62 // TODO(mcgrathr): Under SANITIZER_GO, it's currently used by TSan
63 // to render stack frames, but that should be changed to use
64 // RenderStackFrame.
65 bool SymbolizePC(uptr addr, SymbolizedStack *stack) override;
66
67 // Always claim we succeeded, so that RenderDataInfo will be called.
68 bool SymbolizeData(uptr addr, DataInfo *info) override;
69
70 // May return NULL if demangling failed.
71 // This is used by UBSan for type names, and by ASan for global variable
72 // names. It's expected to return a static buffer that will be reused on each
73 // call.
74 const char *Demangle(const char *name) override;
75};
76
77} // namespace __sanitizer
78
79#endif // SANITIZER_SYMBOLIZER_MARKUP_H
lib/tsan/sanitizer_common/sanitizer_symbolizer_markup_constants.h created+49
......@@ -0,0 +1,49 @@
1//===-- sanitizer_symbolizer_markup_constants.h
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// This file is shared between various sanitizers' runtime libraries.
11//
12// Define string formats and limits for the markup symbolizer.
13//===----------------------------------------------------------------------===//
14#ifndef SANITIZER_SYMBOLIZER_MARKUP_CONSTANTS_H
15#define SANITIZER_SYMBOLIZER_MARKUP_CONSTANTS_H
16
17#include "sanitizer_internal_defs.h"
18
19namespace __sanitizer {
20
21// See the spec at:
22// https://fuchsia.googlesource.com/zircon/+/master/docs/symbolizer_markup.md
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 = "{{{bt:%d:%p}}}";
37
38// Module contextual element.
39constexpr const char *kFormatModule = "{{{module:%zu:%s:elf:%s}}}";
40
41// mmap for a module segment.
42constexpr const char *kFormatMmap = "{{{mmap:%p:0x%zx:load:%d:%s:0x%zx}}}";
43
44// Dump trigger element.
45#define FORMAT_DUMPFILE "{{{dumpfile:%s:%s}}}"
46
47} // namespace __sanitizer
48
49#endif // SANITIZER_SYMBOLIZER_MARKUP_CONSTANTS_H
lib/tsan/sanitizer_common/sanitizer_symbolizer_markup_fuchsia.cpp created+85
......@@ -0,0 +1,85 @@
1//===-- sanitizer_symbolizer_markup_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 various sanitizers' runtime libraries.
10//
11// Fuchsia specific implementation of offline markup symbolizer.
12//===----------------------------------------------------------------------===//
13#include "sanitizer_platform.h"
14
15#if SANITIZER_SYMBOLIZER_MARKUP
16
17# include "sanitizer_common.h"
18# include "sanitizer_stacktrace_printer.h"
19# include "sanitizer_symbolizer.h"
20# include "sanitizer_symbolizer_markup.h"
21# include "sanitizer_symbolizer_markup_constants.h"
22
23namespace __sanitizer {
24
25// This is used by UBSan for type names, and by ASan for global variable names.
26// It's expected to return a static buffer that will be reused on each call.
27const char *Symbolizer::Demangle(const char *name) {
28 static char buffer[kFormatDemangleMax];
29 internal_snprintf(buffer, sizeof(buffer), kFormatDemangle, name);
30 return buffer;
31}
32
33// This is used mostly for suppression matching. Making it work
34// would enable "interceptor_via_lib" suppressions. It's also used
35// once in UBSan to say "in module ..." in a message that also
36// includes an address in the module, so post-processing can already
37// pretty-print that so as to indicate the module.
38bool Symbolizer::GetModuleNameAndOffsetForPC(uptr pc, const char **module_name,
39 uptr *module_address) {
40 return false;
41}
42
43// This is mainly used by hwasan for online symbolization. This isn't needed
44// since hwasan can always just dump stack frames for offline symbolization.
45bool Symbolizer::SymbolizeFrame(uptr addr, FrameInfo *info) { return false; }
46
47// This is used in some places for suppression checking, which we
48// don't really support for Fuchsia. It's also used in UBSan to
49// identify a PC location to a function name, so we always fill in
50// the function member with a string containing markup around the PC
51// value.
52// TODO(mcgrathr): Under SANITIZER_GO, it's currently used by TSan
53// to render stack frames, but that should be changed to use
54// RenderStackFrame.
55SymbolizedStack *Symbolizer::SymbolizePC(uptr addr) {
56 SymbolizedStack *s = SymbolizedStack::New(addr);
57 char buffer[kFormatFunctionMax];
58 internal_snprintf(buffer, sizeof(buffer), kFormatFunction, addr);
59 s->info.function = internal_strdup(buffer);
60 return s;
61}
62
63// Always claim we succeeded, so that RenderDataInfo will be called.
64bool Symbolizer::SymbolizeData(uptr addr, DataInfo *info) {
65 info->Clear();
66 info->start = addr;
67 return true;
68}
69
70// Fuchsia only uses MarkupStackTracePrinter
71StackTracePrinter *StackTracePrinter::NewStackTracePrinter() {
72 return new (GetGlobalLowLevelAllocator()) MarkupStackTracePrinter();
73}
74
75void MarkupStackTracePrinter::RenderContext(InternalScopedString *) {}
76
77Symbolizer *Symbolizer::PlatformInit() {
78 return new (symbolizer_allocator_) Symbolizer({});
79}
80
81void Symbolizer::LateInitialize() { Symbolizer::GetOrInit(); }
82
83} // namespace __sanitizer
84
85#endif // SANITIZER_SYMBOLIZER_MARKUP
lib/tsan/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp+36-31
......@@ -12,6 +12,7 @@
1212//===----------------------------------------------------------------------===//
1313
1414#include "sanitizer_platform.h"
15#include "sanitizer_symbolizer_markup.h"
1516#if SANITIZER_POSIX
1617# include <dlfcn.h> // for dlsym()
1718# include <errno.h>
......@@ -56,7 +57,7 @@ const char *DemangleCXXABI(const char *name) {
5657 __cxxabiv1::__cxa_demangle(name, 0, 0, 0))
5758 return demangled_name;
5859
59 return name;
60 return nullptr;
6061}
6162
6263// As of now, there are no headers for the Swift runtime. Once they are
......@@ -324,9 +325,12 @@ __sanitizer_symbolize_code(const char *ModuleName, u64 ModuleOffset,
324325SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE bool
325326__sanitizer_symbolize_data(const char *ModuleName, u64 ModuleOffset,
326327 char *Buffer, int MaxLength);
328SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE bool
329__sanitizer_symbolize_frame(const char *ModuleName, u64 ModuleOffset,
330 char *Buffer, int MaxLength);
327331SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
328332__sanitizer_symbolize_flush();
329SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE int
333SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE bool
330334__sanitizer_symbolize_demangle(const char *Name, char *Buffer, int MaxLength);
331335SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE bool
332336__sanitizer_symbolize_set_demangle(bool Demangle);
......@@ -337,19 +341,19 @@ __sanitizer_symbolize_set_inline_frames(bool InlineFrames);
337341class InternalSymbolizer final : public SymbolizerTool {
338342 public:
339343 static InternalSymbolizer *get(LowLevelAllocator *alloc) {
340 if (__sanitizer_symbolize_set_demangle)
341 CHECK(__sanitizer_symbolize_set_demangle(common_flags()->demangle));
342 if (__sanitizer_symbolize_set_inline_frames)
343 CHECK(__sanitizer_symbolize_set_inline_frames(
344 common_flags()->symbolize_inline_frames));
345 if (__sanitizer_symbolize_code && __sanitizer_symbolize_data)
346 return new (*alloc) InternalSymbolizer();
347 return 0;
344 // These one is the most used one, so we will use it to detect a presence of
345 // internal symbolizer.
346 if (&__sanitizer_symbolize_code == nullptr)
347 return nullptr;
348 CHECK(__sanitizer_symbolize_set_demangle(common_flags()->demangle));
349 CHECK(__sanitizer_symbolize_set_inline_frames(
350 common_flags()->symbolize_inline_frames));
351 return new (*alloc) InternalSymbolizer();
348352 }
349353
350354 bool SymbolizePC(uptr addr, SymbolizedStack *stack) override {
351355 bool result = __sanitizer_symbolize_code(
352 stack->info.module, stack->info.module_offset, buffer_, kBufferSize);
356 stack->info.module, stack->info.module_offset, buffer_, sizeof(buffer_));
353357 if (result)
354358 ParseSymbolizePCOutput(buffer_, stack);
355359 return result;
......@@ -357,7 +361,7 @@ class InternalSymbolizer final : public SymbolizerTool {
357361
358362 bool SymbolizeData(uptr addr, DataInfo *info) override {
359363 bool result = __sanitizer_symbolize_data(info->module, info->module_offset,
360 buffer_, kBufferSize);
364 buffer_, sizeof(buffer_));
361365 if (result) {
362366 ParseSymbolizeDataOutput(buffer_, info);
363367 info->start += (addr - info->module_offset); // Add the base address.
......@@ -365,34 +369,29 @@ class InternalSymbolizer final : public SymbolizerTool {
365369 return result;
366370 }
367371
368 void Flush() override {
369 if (__sanitizer_symbolize_flush)
370 __sanitizer_symbolize_flush();
372 bool SymbolizeFrame(uptr addr, FrameInfo *info) override {
373 bool result = __sanitizer_symbolize_frame(info->module, info->module_offset,
374 buffer_, sizeof(buffer_));
375 if (result)
376 ParseSymbolizeFrameOutput(buffer_, &info->locals);
377 return result;
371378 }
372379
380 void Flush() override { __sanitizer_symbolize_flush(); }
381
373382 const char *Demangle(const char *name) override {
374 if (__sanitizer_symbolize_demangle) {
375 for (uptr res_length = 1024;
376 res_length <= InternalSizeClassMap::kMaxSize;) {
377 char *res_buff = static_cast<char *>(InternalAlloc(res_length));
378 uptr req_length =
379 __sanitizer_symbolize_demangle(name, res_buff, res_length);
380 if (req_length > res_length) {
381 res_length = req_length + 1;
382 InternalFree(res_buff);
383 continue;
384 }
385 return res_buff;
386 }
383 if (__sanitizer_symbolize_demangle(name, buffer_, sizeof(buffer_))) {
384 char *res_buff = nullptr;
385 ExtractToken(buffer_, "", &res_buff);
386 return res_buff;
387387 }
388 return name;
388 return nullptr;
389389 }
390390
391391 private:
392392 InternalSymbolizer() {}
393393
394 static const int kBufferSize = 16 * 1024;
395 char buffer_[kBufferSize];
394 char buffer_[16 * 1024];
396395};
397396# else // SANITIZER_SUPPORTS_WEAK_HOOKS
398397
......@@ -470,6 +469,12 @@ static void ChooseSymbolizerTools(IntrusiveList<SymbolizerTool> *list,
470469 VReport(2, "Symbolizer is disabled.\n");
471470 return;
472471 }
472 if (common_flags()->enable_symbolizer_markup) {
473 VReport(2, "Using symbolizer markup");
474 SymbolizerTool *tool = new (*allocator) MarkupSymbolizerTool();
475 CHECK(tool);
476 list->push_back(tool);
477 }
473478 if (IsAllocatorOutOfMemory()) {
474479 VReport(2, "Cannot use internal symbolizer: out of memory\n");
475480 } else if (SymbolizerTool *tool = InternalSymbolizer::get(allocator)) {
lib/tsan/sanitizer_common/sanitizer_symbolizer_report.cpp+62-18
......@@ -28,14 +28,41 @@
2828namespace __sanitizer {
2929
3030#if !SANITIZER_GO
31
32static bool FrameIsInternal(const SymbolizedStack *frame) {
33 if (!frame)
34 return true;
35 const char *file = frame->info.file;
36 const char *module = frame->info.module;
37 // On Gentoo, the path is g++-*, so there's *not* a missing /.
38 if (file && (internal_strstr(file, "/compiler-rt/lib/") ||
39 internal_strstr(file, "/include/c++/") ||
40 internal_strstr(file, "/include/g++")))
41 return true;
42 if (file && internal_strstr(file, "\\compiler-rt\\lib\\"))
43 return true;
44 if (module && (internal_strstr(module, "libclang_rt.")))
45 return true;
46 if (module && (internal_strstr(module, "clang_rt.")))
47 return true;
48 return false;
49}
50
51const SymbolizedStack *SkipInternalFrames(const SymbolizedStack *frames) {
52 for (const SymbolizedStack *f = frames; f; f = f->next)
53 if (!FrameIsInternal(f))
54 return f;
55 return nullptr;
56}
57
3158void ReportErrorSummary(const char *error_type, const AddressInfo &info,
3259 const char *alt_tool_name) {
3360 if (!common_flags()->print_summary) return;
3461 InternalScopedString buff;
35 buff.append("%s ", error_type);
36 RenderFrame(&buff, "%L %F", 0, info.address, &info,
37 common_flags()->symbolize_vs_style,
38 common_flags()->strip_path_prefix);
62 buff.AppendF("%s ", error_type);
63 StackTracePrinter::GetOrInit()->RenderFrame(
64 &buff, "%L %F", 0, info.address, &info,
65 common_flags()->symbolize_vs_style, common_flags()->strip_path_prefix);
3966 ReportErrorSummary(buff.data(), alt_tool_name);
4067}
4168#endif
......@@ -75,16 +102,33 @@ void ReportErrorSummary(const char *error_type, const StackTrace *stack,
75102#if !SANITIZER_GO
76103 if (!common_flags()->print_summary)
77104 return;
78 if (stack->size == 0) {
79 ReportErrorSummary(error_type);
80 return;
105
106 // Find first non-internal stack frame.
107 for (uptr i = 0; i < stack->size; ++i) {
108 uptr pc = StackTrace::GetPreviousInstructionPc(stack->trace[i]);
109 SymbolizedStackHolder symbolized_stack(
110 Symbolizer::GetOrInit()->SymbolizePC(pc));
111 if (const SymbolizedStack *frame = symbolized_stack.get()) {
112 if (const SymbolizedStack *summary_frame = SkipInternalFrames(frame)) {
113 ReportErrorSummary(error_type, summary_frame->info, alt_tool_name);
114 return;
115 }
116 }
117 }
118
119 // Fallback to the top one.
120 if (stack->size) {
121 uptr pc = StackTrace::GetPreviousInstructionPc(stack->trace[0]);
122 SymbolizedStackHolder symbolized_stack(
123 Symbolizer::GetOrInit()->SymbolizePC(pc));
124 if (const SymbolizedStack *frame = symbolized_stack.get()) {
125 ReportErrorSummary(error_type, frame->info, alt_tool_name);
126 return;
127 }
81128 }
82 // Currently, we include the first stack frame into the report summary.
83 // Maybe sometimes we need to choose another frame (e.g. skip memcpy/etc).
84 uptr pc = StackTrace::GetPreviousInstructionPc(stack->trace[0]);
85 SymbolizedStack *frame = Symbolizer::GetOrInit()->SymbolizePC(pc);
86 ReportErrorSummary(error_type, frame->info, alt_tool_name);
87 frame->ClearAll();
129
130 // Fallback to a summary without location.
131 ReportErrorSummary(error_type);
88132#endif
89133}
90134
......@@ -148,22 +192,22 @@ static void MaybeReportNonExecRegion(uptr pc) {
148192static void PrintMemoryByte(InternalScopedString *str, const char *before,
149193 u8 byte) {
150194 SanitizerCommonDecorator d;
151 str->append("%s%s%x%x%s ", before, d.MemoryByte(), byte >> 4, byte & 15,
152 d.Default());
195 str->AppendF("%s%s%x%x%s ", before, d.MemoryByte(), byte >> 4, byte & 15,
196 d.Default());
153197}
154198
155199static void MaybeDumpInstructionBytes(uptr pc) {
156200 if (!common_flags()->dump_instruction_bytes || (pc < GetPageSizeCached()))
157201 return;
158202 InternalScopedString str;
159 str.append("First 16 instruction bytes at pc: ");
203 str.AppendF("First 16 instruction bytes at pc: ");
160204 if (IsAccessibleMemoryRange(pc, 16)) {
161205 for (int i = 0; i < 16; ++i) {
162206 PrintMemoryByte(&str, "", ((u8 *)pc)[i]);
163207 }
164 str.append("\n");
208 str.AppendF("\n");
165209 } else {
166 str.append("unaccessible\n");
210 str.AppendF("unaccessible\n");
167211 }
168212 Report("%s", str.data());
169213}
lib/tsan/sanitizer_common/sanitizer_symbolizer_report_fuchsia.cpp created+33
......@@ -0,0 +1,33 @@
1//===-- sanitizer_symbolizer_report_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// Implementation of the report functions for fuchsia.
11//
12//===----------------------------------------------------------------------===//
13
14#include "sanitizer_platform.h"
15
16#if SANITIZER_SYMBOLIZER_MARKUP
17
18# include "sanitizer_common.h"
19
20namespace __sanitizer {
21void StartReportDeadlySignal() {}
22
23void ReportDeadlySignal(const SignalContext &sig, u32 tid,
24 UnwindSignalStackCallbackType unwind,
25 const void *unwind_context) {}
26
27void HandleDeadlySignal(void *siginfo, void *context, u32 tid,
28 UnwindSignalStackCallbackType unwind,
29 const void *unwind_context) {}
30
31} // namespace __sanitizer
32
33#endif // SANITIZER_SYMBOLIZER_MARKUP
lib/tsan/sanitizer_common/sanitizer_symbolizer_win.cpp+2-4
......@@ -175,9 +175,7 @@ const char *WinSymbolizerTool::Demangle(const char *name) {
175175 return name;
176176}
177177
178const char *Symbolizer::PlatformDemangle(const char *name) {
179 return name;
180}
178const char *Symbolizer::PlatformDemangle(const char *name) { return nullptr; }
181179
182180namespace {
183181struct ScopedHandle {
......@@ -233,7 +231,7 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() {
233231 CHECK(!internal_strchr(arg, '"') && "quotes in args unsupported");
234232 CHECK(arglen > 0 && arg[arglen - 1] != '\\' &&
235233 "args ending in backslash and empty args unsupported");
236 command_line.append("\"%s\" ", arg);
234 command_line.AppendF("\"%s\" ", arg);
237235 }
238236 VReport(3, "Launching symbolizer command: %s\n", command_line.data());
239237
lib/tsan/sanitizer_common/sanitizer_syscall_linux_hexagon.inc created+131
......@@ -0,0 +1,131 @@
1//===-- sanitizer_syscall_linux_hexagon.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/hexagon.
10//
11//===----------------------------------------------------------------------===//
12
13#define SYSCALL(name) __NR_##name
14
15#define __internal_syscall_LL_E(x) \
16 ((union { \
17 long long ll; \
18 long l[2]; \
19 }){.ll = x}) \
20 .l[0], \
21 ((union { \
22 long long ll; \
23 long l[2]; \
24 }){.ll = x}) \
25 .l[1]
26#define __internal_syscall_LL_O(x) 0, __SYSCALL_LL_E((x))
27
28#define __asm_syscall(...) \
29 do { \
30 __asm__ __volatile__("trap0(#1)" : "=r"(r0) : __VA_ARGS__ : "memory"); \
31 return r0; \
32 } while (0)
33
34#define __internal_syscall0(n) (__internal_syscall)(n)
35
36static uptr __internal_syscall(long n) {
37 register u32 r6 __asm__("r6") = n;
38 register u32 r0 __asm__("r0");
39 __asm_syscall("r"(r6));
40}
41
42#define __internal_syscall1(n, a1) (__internal_syscall)(n, (long)(a1))
43
44static uptr __internal_syscall(long n, long a) {
45 register u32 r6 __asm__("r6") = n;
46 register u32 r0 __asm__("r0") = a;
47 __asm_syscall("r"(r6), "0"(r0));
48}
49
50#define __internal_syscall2(n, a1, a2) \
51 (__internal_syscall)(n, (long)(a1), (long)(a2))
52
53static uptr __internal_syscall(long n, long a, long b) {
54 register u32 r6 __asm__("r6") = n;
55 register u32 r0 __asm__("r0") = a;
56 register u32 r1 __asm__("r1") = b;
57 __asm_syscall("r"(r6), "0"(r0), "r"(r1));
58}
59
60#define __internal_syscall3(n, a1, a2, a3) \
61 (__internal_syscall)(n, (long)(a1), (long)(a2), (long)(a3))
62
63static uptr __internal_syscall(long n, long a, long b, long c) {
64 register u32 r6 __asm__("r6") = n;
65 register u32 r0 __asm__("r0") = a;
66 register u32 r1 __asm__("r1") = b;
67 register u32 r2 __asm__("r2") = c;
68 __asm_syscall("r"(r6), "0"(r0), "r"(r1), "r"(r2));
69}
70
71#define __internal_syscall4(n, a1, a2, a3, a4) \
72 (__internal_syscall)(n, (long)(a1), (long)(a2), (long)(a3), (long)(a4))
73
74static uptr __internal_syscall(long n, long a, long b, long c, long d) {
75 register u32 r6 __asm__("r6") = n;
76 register u32 r0 __asm__("r0") = a;
77 register u32 r1 __asm__("r1") = b;
78 register u32 r2 __asm__("r2") = c;
79 register u32 r3 __asm__("r3") = d;
80 __asm_syscall("r"(r6), "0"(r0), "r"(r1), "r"(r2), "r"(r3));
81}
82
83#define __internal_syscall5(n, a1, a2, a3, a4, a5) \
84 (__internal_syscall)(n, (long)(a1), (long)(a2), (long)(a3), (long)(a4), \
85 (long)(a5))
86
87static uptr __internal_syscall(long n, long a, long b, long c, long d, long e) {
88 register u32 r6 __asm__("r6") = n;
89 register u32 r0 __asm__("r0") = a;
90 register u32 r1 __asm__("r1") = b;
91 register u32 r2 __asm__("r2") = c;
92 register u32 r3 __asm__("r3") = d;
93 register u32 r4 __asm__("r4") = e;
94 __asm_syscall("r"(r6), "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4));
95}
96
97#define __internal_syscall6(n, a1, a2, a3, a4, a5, a6) \
98 (__internal_syscall)(n, (long)(a1), (long)(a2), (long)(a3), (long)(a4), \
99 (long)(a5), (long)(a6))
100
101static uptr __internal_syscall(long n, long a, long b, long c, long d, long e,
102 long f) {
103 register u32 r6 __asm__("r6") = n;
104 register u32 r0 __asm__("r0") = a;
105 register u32 r1 __asm__("r1") = b;
106 register u32 r2 __asm__("r2") = c;
107 register u32 r3 __asm__("r3") = d;
108 register u32 r4 __asm__("r4") = e;
109 register u32 r5 __asm__("r5") = f;
110 __asm_syscall("r"(r6), "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5));
111}
112
113#define __SYSCALL_NARGS_X(a1, a2, a3, a4, a5, a6, a7, a8, n, ...) n
114#define __SYSCALL_NARGS(...) \
115 __SYSCALL_NARGS_X(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0, )
116#define __SYSCALL_CONCAT_X(a, b) a##b
117#define __SYSCALL_CONCAT(a, b) __SYSCALL_CONCAT_X(a, b)
118#define __SYSCALL_DISP(b, ...) \
119 __SYSCALL_CONCAT(b, __SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__)
120
121#define internal_syscall(...) __SYSCALL_DISP(__internal_syscall, __VA_ARGS__)
122
123// Helper function used to avoid clobbering of errno.
124bool internal_iserror(uptr retval, int *rverrno) {
125 if (retval >= (uptr)-4095) {
126 if (rverrno)
127 *rverrno = -retval;
128 return true;
129 }
130 return false;
131}
lib/tsan/sanitizer_common/sanitizer_syscall_linux_loongarch64.inc created+171
......@@ -0,0 +1,171 @@
1//===-- sanitizer_syscall_linux_loongarch64.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
10// Linux/loongarch64.
11//
12//===----------------------------------------------------------------------===//
13
14// About local register variables:
15// https://gcc.gnu.org/onlinedocs/gcc/Local-Register-Variables.html#Local-Register-Variables
16//
17// Kernel ABI:
18// https://lore.kernel.org/loongarch/1f353678-3398-e30b-1c87-6edb278f74db@xen0n.name/T/#m1613bc86c2d7bf5f6da92bd62984302bfd699a2f
19// syscall number is placed in a7
20// parameters, if present, are placed in a0-a6
21// upon return:
22// the return value is placed in a0
23// t0-t8 should be considered clobbered
24// all other registers are preserved
25#define SYSCALL(name) __NR_##name
26
27#define INTERNAL_SYSCALL_CLOBBERS \
28 "memory", "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8"
29
30static uptr __internal_syscall(u64 nr) {
31 register u64 a7 asm("$a7") = nr;
32 register u64 a0 asm("$a0");
33 __asm__ volatile("syscall 0\n\t"
34 : "=r"(a0)
35 : "r"(a7)
36 : INTERNAL_SYSCALL_CLOBBERS);
37 return a0;
38}
39#define __internal_syscall0(n) (__internal_syscall)(n)
40
41static uptr __internal_syscall(u64 nr, u64 arg1) {
42 register u64 a7 asm("$a7") = nr;
43 register u64 a0 asm("$a0") = arg1;
44 __asm__ volatile("syscall 0\n\t"
45 : "+r"(a0)
46 : "r"(a7)
47 : INTERNAL_SYSCALL_CLOBBERS);
48 return a0;
49}
50#define __internal_syscall1(n, a1) (__internal_syscall)(n, (u64)(a1))
51
52static uptr __internal_syscall(u64 nr, u64 arg1, long arg2) {
53 register u64 a7 asm("$a7") = nr;
54 register u64 a0 asm("$a0") = arg1;
55 register u64 a1 asm("$a1") = arg2;
56 __asm__ volatile("syscall 0\n\t"
57 : "+r"(a0)
58 : "r"(a7), "r"(a1)
59 : INTERNAL_SYSCALL_CLOBBERS);
60 return a0;
61}
62#define __internal_syscall2(n, a1, a2) \
63 (__internal_syscall)(n, (u64)(a1), (long)(a2))
64
65static uptr __internal_syscall(u64 nr, u64 arg1, long arg2, long arg3) {
66 register u64 a7 asm("$a7") = nr;
67 register u64 a0 asm("$a0") = arg1;
68 register u64 a1 asm("$a1") = arg2;
69 register u64 a2 asm("$a2") = arg3;
70 __asm__ volatile("syscall 0\n\t"
71 : "+r"(a0)
72 : "r"(a7), "r"(a1), "r"(a2)
73 : INTERNAL_SYSCALL_CLOBBERS);
74 return a0;
75}
76#define __internal_syscall3(n, a1, a2, a3) \
77 (__internal_syscall)(n, (u64)(a1), (long)(a2), (long)(a3))
78
79static uptr __internal_syscall(u64 nr, u64 arg1, long arg2, long arg3,
80 u64 arg4) {
81 register u64 a7 asm("$a7") = nr;
82 register u64 a0 asm("$a0") = arg1;
83 register u64 a1 asm("$a1") = arg2;
84 register u64 a2 asm("$a2") = arg3;
85 register u64 a3 asm("$a3") = arg4;
86 __asm__ volatile("syscall 0\n\t"
87 : "+r"(a0)
88 : "r"(a7), "r"(a1), "r"(a2), "r"(a3)
89 : INTERNAL_SYSCALL_CLOBBERS);
90 return a0;
91}
92#define __internal_syscall4(n, a1, a2, a3, a4) \
93 (__internal_syscall)(n, (u64)(a1), (long)(a2), (long)(a3), (long)(a4))
94
95static uptr __internal_syscall(u64 nr, u64 arg1, long arg2, long arg3, u64 arg4,
96 long arg5) {
97 register u64 a7 asm("$a7") = nr;
98 register u64 a0 asm("$a0") = arg1;
99 register u64 a1 asm("$a1") = arg2;
100 register u64 a2 asm("$a2") = arg3;
101 register u64 a3 asm("$a3") = arg4;
102 register u64 a4 asm("$a4") = arg5;
103 __asm__ volatile("syscall 0\n\t"
104 : "+r"(a0)
105 : "r"(a7), "r"(a1), "r"(a2), "r"(a3), "r"(a4)
106 : INTERNAL_SYSCALL_CLOBBERS);
107 return a0;
108}
109#define __internal_syscall5(n, a1, a2, a3, a4, a5) \
110 (__internal_syscall)(n, (u64)(a1), (long)(a2), (long)(a3), (long)(a4), \
111 (u64)(a5))
112
113static uptr __internal_syscall(u64 nr, u64 arg1, long arg2, long arg3, u64 arg4,
114 long arg5, long arg6) {
115 register u64 a7 asm("$a7") = nr;
116 register u64 a0 asm("$a0") = arg1;
117 register u64 a1 asm("$a1") = arg2;
118 register u64 a2 asm("$a2") = arg3;
119 register u64 a3 asm("$a3") = arg4;
120 register u64 a4 asm("$a4") = arg5;
121 register u64 a5 asm("$a5") = arg6;
122 __asm__ volatile("syscall 0\n\t"
123 : "+r"(a0)
124 : "r"(a7), "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5)
125 : INTERNAL_SYSCALL_CLOBBERS);
126 return a0;
127}
128#define __internal_syscall6(n, a1, a2, a3, a4, a5, a6) \
129 (__internal_syscall)(n, (u64)(a1), (long)(a2), (long)(a3), (long)(a4), \
130 (u64)(a5), (long)(a6))
131
132static uptr __internal_syscall(u64 nr, u64 arg1, long arg2, long arg3, u64 arg4,
133 long arg5, long arg6, long arg7) {
134 register u64 a7 asm("$a7") = nr;
135 register u64 a0 asm("$a0") = arg1;
136 register u64 a1 asm("$a1") = arg2;
137 register u64 a2 asm("$a2") = arg3;
138 register u64 a3 asm("$a3") = arg4;
139 register u64 a4 asm("$a4") = arg5;
140 register u64 a5 asm("$a5") = arg6;
141 register u64 a6 asm("$a6") = arg7;
142 __asm__ volatile("syscall 0\n\t"
143 : "+r"(a0)
144 : "r"(a7), "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5),
145 "r"(a6)
146 : INTERNAL_SYSCALL_CLOBBERS);
147 return a0;
148}
149#define __internal_syscall7(n, a1, a2, a3, a4, a5, a6, a7) \
150 (__internal_syscall)(n, (u64)(a1), (long)(a2), (long)(a3), (long)(a4), \
151 (u64)(a5), (long)(a6), (long)(a7))
152
153#define __SYSCALL_NARGS_X(a1, a2, a3, a4, a5, a6, a7, a8, n, ...) n
154#define __SYSCALL_NARGS(...) \
155 __SYSCALL_NARGS_X(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0, )
156#define __SYSCALL_CONCAT_X(a, b) a##b
157#define __SYSCALL_CONCAT(a, b) __SYSCALL_CONCAT_X(a, b)
158#define __SYSCALL_DISP(b, ...) \
159 __SYSCALL_CONCAT(b, __SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__)
160
161#define internal_syscall(...) __SYSCALL_DISP(__internal_syscall, __VA_ARGS__)
162
163// Helper function used to avoid clobbering of errno.
164bool internal_iserror(uptr retval, int *internal_errno) {
165 if (retval >= (uptr)-4095) {
166 if (internal_errno)
167 *internal_errno = -retval;
168 return true;
169 }
170 return false;
171}
lib/tsan/sanitizer_common/sanitizer_syscall_linux_riscv64.inc created+174
......@@ -0,0 +1,174 @@
1//===-- sanitizer_syscall_linux_riscv64.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/riscv64.
10//
11//===----------------------------------------------------------------------===//
12
13// About local register variables:
14// https://gcc.gnu.org/onlinedocs/gcc/Local-Register-Variables.html#Local-Register-Variables
15//
16// Kernel ABI...
17// To my surprise I haven't found much information regarding it.
18// Kernel source and internet browsing shows that:
19// syscall number is passed in a7
20// (http://man7.org/linux/man-pages/man2/syscall.2.html) results are return in
21// a0 and a1 (http://man7.org/linux/man-pages/man2/syscall.2.html) arguments
22// are passed in: a0-a7 (see below)
23//
24// Regarding the arguments. The only "documentation" I could find is
25// this comment (!!!) by Bruce Hold on google forums (!!!):
26// https://groups.google.com/a/groups.riscv.org/forum/#!topic/sw-dev/exbrzM3GZDQ
27// Confirmed by inspecting glibc sources.
28// Great way to document things.
29#define SYSCALL(name) __NR_##name
30
31#define INTERNAL_SYSCALL_CLOBBERS "memory"
32
33static uptr __internal_syscall(u64 nr) {
34 register u64 a7 asm("a7") = nr;
35 register u64 a0 asm("a0");
36 __asm__ volatile("ecall\n\t"
37 : "=r"(a0)
38 : "r"(a7)
39 : INTERNAL_SYSCALL_CLOBBERS);
40 return a0;
41}
42#define __internal_syscall0(n) (__internal_syscall)(n)
43
44static uptr __internal_syscall(u64 nr, u64 arg1) {
45 register u64 a7 asm("a7") = nr;
46 register u64 a0 asm("a0") = arg1;
47 __asm__ volatile("ecall\n\t"
48 : "+r"(a0)
49 : "r"(a7)
50 : INTERNAL_SYSCALL_CLOBBERS);
51 return a0;
52}
53#define __internal_syscall1(n, a1) (__internal_syscall)(n, (u64)(a1))
54
55static uptr __internal_syscall(u64 nr, u64 arg1, long arg2) {
56 register u64 a7 asm("a7") = nr;
57 register u64 a0 asm("a0") = arg1;
58 register u64 a1 asm("a1") = arg2;
59 __asm__ volatile("ecall\n\t"
60 : "+r"(a0)
61 : "r"(a7), "r"(a1)
62 : INTERNAL_SYSCALL_CLOBBERS);
63 return a0;
64}
65#define __internal_syscall2(n, a1, a2) \
66 (__internal_syscall)(n, (u64)(a1), (long)(a2))
67
68static uptr __internal_syscall(u64 nr, u64 arg1, long arg2, long arg3) {
69 register u64 a7 asm("a7") = nr;
70 register u64 a0 asm("a0") = arg1;
71 register u64 a1 asm("a1") = arg2;
72 register u64 a2 asm("a2") = arg3;
73 __asm__ volatile("ecall\n\t"
74 : "+r"(a0)
75 : "r"(a7), "r"(a1), "r"(a2)
76 : INTERNAL_SYSCALL_CLOBBERS);
77 return a0;
78}
79#define __internal_syscall3(n, a1, a2, a3) \
80 (__internal_syscall)(n, (u64)(a1), (long)(a2), (long)(a3))
81
82static uptr __internal_syscall(u64 nr, u64 arg1, long arg2, long arg3,
83 u64 arg4) {
84 register u64 a7 asm("a7") = nr;
85 register u64 a0 asm("a0") = arg1;
86 register u64 a1 asm("a1") = arg2;
87 register u64 a2 asm("a2") = arg3;
88 register u64 a3 asm("a3") = arg4;
89 __asm__ volatile("ecall\n\t"
90 : "+r"(a0)
91 : "r"(a7), "r"(a1), "r"(a2), "r"(a3)
92 : INTERNAL_SYSCALL_CLOBBERS);
93 return a0;
94}
95#define __internal_syscall4(n, a1, a2, a3, a4) \
96 (__internal_syscall)(n, (u64)(a1), (long)(a2), (long)(a3), (long)(a4))
97
98static uptr __internal_syscall(u64 nr, u64 arg1, long arg2, long arg3, u64 arg4,
99 long arg5) {
100 register u64 a7 asm("a7") = nr;
101 register u64 a0 asm("a0") = arg1;
102 register u64 a1 asm("a1") = arg2;
103 register u64 a2 asm("a2") = arg3;
104 register u64 a3 asm("a3") = arg4;
105 register u64 a4 asm("a4") = arg5;
106 __asm__ volatile("ecall\n\t"
107 : "+r"(a0)
108 : "r"(a7), "r"(a1), "r"(a2), "r"(a3), "r"(a4)
109 : INTERNAL_SYSCALL_CLOBBERS);
110 return a0;
111}
112#define __internal_syscall5(n, a1, a2, a3, a4, a5) \
113 (__internal_syscall)(n, (u64)(a1), (long)(a2), (long)(a3), (long)(a4), \
114 (u64)(a5))
115
116static uptr __internal_syscall(u64 nr, u64 arg1, long arg2, long arg3, u64 arg4,
117 long arg5, long arg6) {
118 register u64 a7 asm("a7") = nr;
119 register u64 a0 asm("a0") = arg1;
120 register u64 a1 asm("a1") = arg2;
121 register u64 a2 asm("a2") = arg3;
122 register u64 a3 asm("a3") = arg4;
123 register u64 a4 asm("a4") = arg5;
124 register u64 a5 asm("a5") = arg6;
125 __asm__ volatile("ecall\n\t"
126 : "+r"(a0)
127 : "r"(a7), "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5)
128 : INTERNAL_SYSCALL_CLOBBERS);
129 return a0;
130}
131#define __internal_syscall6(n, a1, a2, a3, a4, a5, a6) \
132 (__internal_syscall)(n, (u64)(a1), (long)(a2), (long)(a3), (long)(a4), \
133 (u64)(a5), (long)(a6))
134
135static uptr __internal_syscall(u64 nr, u64 arg1, long arg2, long arg3, u64 arg4,
136 long arg5, long arg6, long arg7) {
137 register u64 a7 asm("a7") = nr;
138 register u64 a0 asm("a0") = arg1;
139 register u64 a1 asm("a1") = arg2;
140 register u64 a2 asm("a2") = arg3;
141 register u64 a3 asm("a3") = arg4;
142 register u64 a4 asm("a4") = arg5;
143 register u64 a5 asm("a5") = arg6;
144 register u64 a6 asm("a6") = arg7;
145 __asm__ volatile("ecall\n\t"
146 : "+r"(a0)
147 : "r"(a7), "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5),
148 "r"(a6)
149 : INTERNAL_SYSCALL_CLOBBERS);
150 return a0;
151}
152#define __internal_syscall7(n, a1, a2, a3, a4, a5, a6, a7) \
153 (__internal_syscall)(n, (u64)(a1), (long)(a2), (long)(a3), (long)(a4), \
154 (u64)(a5), (long)(a6), (long)(a7))
155
156#define __SYSCALL_NARGS_X(a1, a2, a3, a4, a5, a6, a7, a8, n, ...) n
157#define __SYSCALL_NARGS(...) \
158 __SYSCALL_NARGS_X(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0, )
159#define __SYSCALL_CONCAT_X(a, b) a##b
160#define __SYSCALL_CONCAT(a, b) __SYSCALL_CONCAT_X(a, b)
161#define __SYSCALL_DISP(b, ...) \
162 __SYSCALL_CONCAT(b, __SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__)
163
164#define internal_syscall(...) __SYSCALL_DISP(__internal_syscall, __VA_ARGS__)
165
166// Helper function used to avoid clobbering of errno.
167bool internal_iserror(uptr retval, int *rverrno) {
168 if (retval >= (uptr)-4095) {
169 if (rverrno)
170 *rverrno = -retval;
171 return true;
172 }
173 return false;
174}
lib/tsan/sanitizer_common/sanitizer_thread_arg_retval.cpp+19-4
......@@ -23,6 +23,9 @@ void ThreadArgRetval::CreateLocked(uptr thread, bool detached,
2323 Data& t = data_[thread];
2424 t = {};
2525 t.gen = gen_++;
26 static_assert(sizeof(gen_) == sizeof(u32) && kInvalidGen == UINT32_MAX);
27 if (gen_ == kInvalidGen)
28 gen_ = 0;
2629 t.detached = detached;
2730 t.args = args;
2831}
......@@ -53,16 +56,28 @@ void ThreadArgRetval::Finish(uptr thread, void* retval) {
5356u32 ThreadArgRetval::BeforeJoin(uptr thread) const {
5457 __sanitizer::Lock lock(&mtx_);
5558 auto t = data_.find(thread);
56 CHECK(t);
57 CHECK(!t->second.detached);
58 return t->second.gen;
59 if (t && !t->second.detached) {
60 return t->second.gen;
61 }
62 if (!common_flags()->detect_invalid_join)
63 return kInvalidGen;
64 const char* reason = "unknown";
65 if (!t) {
66 reason = "already joined";
67 } else if (t->second.detached) {
68 reason = "detached";
69 }
70 Report("ERROR: %s: Joining %s thread, aborting.\n", SanitizerToolName,
71 reason);
72 Die();
5973}
6074
6175void ThreadArgRetval::AfterJoin(uptr thread, u32 gen) {
6276 __sanitizer::Lock lock(&mtx_);
6377 auto t = data_.find(thread);
6478 if (!t || gen != t->second.gen) {
65 // Thread was reused and erased by any other event.
79 // Thread was reused and erased by any other event, or we had an invalid
80 // join.
6681 return;
6782 }
6883 CHECK(!t->second.detached);
lib/tsan/sanitizer_common/sanitizer_thread_arg_retval.h+1
......@@ -93,6 +93,7 @@ class SANITIZER_MUTEX ThreadArgRetval {
9393 // will keep pointers alive forever, missing leaks caused by cancelation.
9494
9595 private:
96 static const u32 kInvalidGen = UINT32_MAX;
9697 struct Data {
9798 Args args;
9899 u32 gen; // Avoid collision if thread id re-used.
lib/tsan/sanitizer_common/sanitizer_tls_get_addr.cpp+8-7
......@@ -121,25 +121,26 @@ DTLS::DTV *DTLS_on_tls_get_addr(void *arg_void, void *res,
121121 uptr tls_size = 0;
122122 uptr tls_beg = reinterpret_cast<uptr>(res) - arg->offset - kDtvOffset;
123123 VReport(2,
124 "__tls_get_addr: %p {0x%zx,0x%zx} => %p; tls_beg: 0x%zx; sp: %p "
124 "__tls_get_addr: %p {0x%zx,0x%zx} => %p; tls_beg: %p; sp: %p "
125125 "num_live_dtls %zd\n",
126 (void *)arg, arg->dso_id, arg->offset, res, tls_beg, (void *)&tls_beg,
126 (void *)arg, arg->dso_id, arg->offset, res, (void *)tls_beg,
127 (void *)&tls_beg,
127128 atomic_load(&number_of_live_dtls, memory_order_relaxed));
128129 if (dtls.last_memalign_ptr == tls_beg) {
129130 tls_size = dtls.last_memalign_size;
130 VReport(2, "__tls_get_addr: glibc <=2.24 suspected; tls={0x%zx,0x%zx}\n",
131 tls_beg, tls_size);
131 VReport(2, "__tls_get_addr: glibc <=2.24 suspected; tls={%p,0x%zx}\n",
132 (void *)tls_beg, tls_size);
132133 } else if (tls_beg >= static_tls_begin && tls_beg < static_tls_end) {
133134 // This is the static TLS block which was initialized / unpoisoned at thread
134135 // creation.
135 VReport(2, "__tls_get_addr: static tls: 0x%zx\n", tls_beg);
136 VReport(2, "__tls_get_addr: static tls: %p\n", (void *)tls_beg);
136137 tls_size = 0;
137138 } else if (const void *start =
138139 __sanitizer_get_allocated_begin((void *)tls_beg)) {
139140 tls_beg = (uptr)start;
140141 tls_size = __sanitizer_get_allocated_size(start);
141 VReport(2, "__tls_get_addr: glibc >=2.25 suspected; tls={0x%zx,0x%zx}\n",
142 tls_beg, tls_size);
142 VReport(2, "__tls_get_addr: glibc >=2.25 suspected; tls={%p,0x%zx}\n",
143 (void *)tls_beg, tls_size);
143144 } else {
144145 VReport(2, "__tls_get_addr: Can't guess glibc version\n");
145146 // This may happen inside the DTOR of main thread, so just ignore it.
lib/tsan/sanitizer_common/sanitizer_unwind_fuchsia.cpp created+66
......@@ -0,0 +1,66 @@
1//===------------------ sanitizer_unwind_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/// Sanitizer unwind Fuchsia specific functions.
11//
12//===----------------------------------------------------------------------===//
13
14#include "sanitizer_platform.h"
15#if SANITIZER_FUCHSIA
16
17# include <limits.h>
18# include <unwind.h>
19
20# include "sanitizer_common.h"
21# include "sanitizer_stacktrace.h"
22
23namespace __sanitizer {
24
25# if SANITIZER_CAN_SLOW_UNWIND
26struct UnwindTraceArg {
27 BufferedStackTrace *stack;
28 u32 max_depth;
29};
30
31_Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) {
32 UnwindTraceArg *arg = static_cast<UnwindTraceArg *>(param);
33 CHECK_LT(arg->stack->size, arg->max_depth);
34 uptr pc = _Unwind_GetIP(ctx);
35 if (pc < GetPageSizeCached())
36 return _URC_NORMAL_STOP;
37 arg->stack->trace_buffer[arg->stack->size++] = pc;
38 return (arg->stack->size == arg->max_depth ? _URC_NORMAL_STOP
39 : _URC_NO_REASON);
40}
41
42void BufferedStackTrace::UnwindSlow(uptr pc, u32 max_depth) {
43 CHECK_GE(max_depth, 2);
44 size = 0;
45 UnwindTraceArg arg = {this, Min(max_depth + 1, kStackTraceMax)};
46 _Unwind_Backtrace(Unwind_Trace, &arg);
47 CHECK_GT(size, 0);
48 // We need to pop a few frames so that pc is on top.
49 uptr to_pop = LocatePcInTrace(pc);
50 // trace_buffer[0] belongs to the current function so we always pop it,
51 // unless there is only 1 frame in the stack trace (1 frame is always better
52 // than 0!).
53 PopStackFrames(Min(to_pop, static_cast<uptr>(1)));
54 trace_buffer[0] = pc;
55}
56
57void BufferedStackTrace::UnwindSlow(uptr pc, void *context, u32 max_depth) {
58 CHECK(context);
59 CHECK_GE(max_depth, 2);
60 UNREACHABLE("signal context doesn't exist");
61}
62# endif // SANITIZER_CAN_SLOW_UNWIND
63
64} // namespace __sanitizer
65
66#endif // SANITIZER_FUCHSIA
lib/tsan/sanitizer_common/sanitizer_unwind_win.cpp+7
......@@ -70,10 +70,17 @@ void BufferedStackTrace::UnwindSlow(uptr pc, void *context, u32 max_depth) {
7070 stack_frame.AddrStack.Offset = ctx.Rsp;
7171# endif
7272# else
73# if SANITIZER_ARM
74 int machine_type = IMAGE_FILE_MACHINE_ARM;
75 stack_frame.AddrPC.Offset = ctx.Pc;
76 stack_frame.AddrFrame.Offset = ctx.R11;
77 stack_frame.AddrStack.Offset = ctx.Sp;
78# else
7379 int machine_type = IMAGE_FILE_MACHINE_I386;
7480 stack_frame.AddrPC.Offset = ctx.Eip;
7581 stack_frame.AddrFrame.Offset = ctx.Ebp;
7682 stack_frame.AddrStack.Offset = ctx.Esp;
83# endif
7784# endif
7885 stack_frame.AddrPC.Mode = AddrModeFlat;
7986 stack_frame.AddrFrame.Mode = AddrModeFlat;
lib/tsan/sanitizer_common/sanitizer_win.cpp+13-12
......@@ -144,7 +144,7 @@ void *MmapOrDie(uptr size, const char *mem_type, bool raw_report) {
144144 return rv;
145145}
146146
147void UnmapOrDie(void *addr, uptr size) {
147void UnmapOrDie(void *addr, uptr size, bool raw_report) {
148148 if (!size || !addr)
149149 return;
150150
......@@ -156,10 +156,7 @@ void UnmapOrDie(void *addr, uptr size) {
156156 // fails try MEM_DECOMMIT.
157157 if (VirtualFree(addr, 0, MEM_RELEASE) == 0) {
158158 if (VirtualFree(addr, size, MEM_DECOMMIT) == 0) {
159 Report("ERROR: %s failed to "
160 "deallocate 0x%zx (%zd) bytes at address %p (error code: %d)\n",
161 SanitizerToolName, size, size, addr, GetLastError());
162 CHECK("unable to unmap" && 0);
159 ReportMunmapFailureAndDie(addr, size, GetLastError(), raw_report);
163160 }
164161 }
165162}
......@@ -279,8 +276,8 @@ void *MmapFixedOrDie(uptr fixed_addr, uptr size, const char *name) {
279276 MEM_COMMIT, PAGE_READWRITE);
280277 if (p == 0) {
281278 char mem_type[30];
282 internal_snprintf(mem_type, sizeof(mem_type), "memory at address 0x%zx",
283 fixed_addr);
279 internal_snprintf(mem_type, sizeof(mem_type), "memory at address %p",
280 (void *)fixed_addr);
284281 ReportMmapFailureAndDie(size, mem_type, "allocate", GetLastError());
285282 }
286283 return p;
......@@ -311,8 +308,8 @@ void *MmapFixedOrDieOnFatalError(uptr fixed_addr, uptr size, const char *name) {
311308 MEM_COMMIT, PAGE_READWRITE);
312309 if (p == 0) {
313310 char mem_type[30];
314 internal_snprintf(mem_type, sizeof(mem_type), "memory at address 0x%zx",
315 fixed_addr);
311 internal_snprintf(mem_type, sizeof(mem_type), "memory at address %p",
312 (void *)fixed_addr);
316313 return ReturnNullptrOnOOMOrDie(size, mem_type, "allocate");
317314 }
318315 return p;
......@@ -387,9 +384,8 @@ bool DontDumpShadowMemory(uptr addr, uptr length) {
387384}
388385
389386uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale,
390 uptr min_shadow_base_alignment,
391 UNUSED uptr &high_mem_end) {
392 const uptr granularity = GetMmapGranularity();
387 uptr min_shadow_base_alignment, UNUSED uptr &high_mem_end,
388 uptr granularity) {
393389 const uptr alignment =
394390 Max<uptr>(granularity << shadow_scale, 1ULL << min_shadow_base_alignment);
395391 const uptr left_padding =
......@@ -996,8 +992,13 @@ void SignalContext::InitPcSpBp() {
996992 sp = (uptr)context_record->Rsp;
997993# endif
998994# else
995# if SANITIZER_ARM
996 bp = (uptr)context_record->R11;
997 sp = (uptr)context_record->Sp;
998# else
999999 bp = (uptr)context_record->Ebp;
10001000 sp = (uptr)context_record->Esp;
1001# endif
10011002# endif
10021003}
10031004
lib/tsan/tsan_debugging.cpp+3-1
......@@ -35,7 +35,9 @@ static const char *ReportTypeDescription(ReportType typ) {
3535 case ReportTypeSignalUnsafe: return "signal-unsafe-call";
3636 case ReportTypeErrnoInSignal: return "errno-in-signal-handler";
3737 case ReportTypeDeadlock: return "lock-order-inversion";
38 // No default case so compiler warns us if we miss one
38 case ReportTypeMutexHeldWrongContext:
39 return "mutex-held-in-wrong-context";
40 // No default case so compiler warns us if we miss one
3941 }
4042 UNREACHABLE("missing case");
4143}
lib/tsan/tsan_defs.h+1-1
......@@ -30,7 +30,7 @@
3030# define __MM_MALLOC_H
3131# include <emmintrin.h>
3232# include <smmintrin.h>
33# define VECTOR_ALIGNED ALIGNED(16)
33# define VECTOR_ALIGNED alignas(16)
3434typedef __m128i m128;
3535#else
3636# define VECTOR_ALIGNED
lib/tsan/tsan_dispatch_defs.h-7
......@@ -56,13 +56,6 @@ extern const dispatch_block_t _dispatch_data_destructor_munmap;
5656# define DISPATCH_NOESCAPE
5757#endif
5858
59#if SANITIZER_APPLE
60# define SANITIZER_WEAK_IMPORT extern "C" __attribute((weak_import))
61#else
62# define SANITIZER_WEAK_IMPORT extern "C" __attribute((weak))
63#endif
64
65
6659// Data types used in dispatch APIs
6760typedef unsigned long size_t;
6861typedef unsigned long uintptr_t;
lib/tsan/tsan_interceptors_posix.cpp+93-42
......@@ -14,6 +14,7 @@
1414
1515#include "sanitizer_common/sanitizer_atomic.h"
1616#include "sanitizer_common/sanitizer_errno.h"
17#include "sanitizer_common/sanitizer_glibc_version.h"
1718#include "sanitizer_common/sanitizer_libc.h"
1819#include "sanitizer_common/sanitizer_linux.h"
1920#include "sanitizer_common/sanitizer_platform_limits_netbsd.h"
......@@ -81,6 +82,8 @@ struct ucontext_t {
8182#define PTHREAD_ABI_BASE "GLIBC_2.17"
8283#elif SANITIZER_LOONGARCH64
8384#define PTHREAD_ABI_BASE "GLIBC_2.36"
85#elif SANITIZER_RISCV64
86# define PTHREAD_ABI_BASE "GLIBC_2.27"
8487#endif
8588
8689extern "C" int pthread_attr_init(void *attr);
......@@ -205,7 +208,7 @@ struct AtExitCtx {
205208struct InterceptorContext {
206209 // The object is 64-byte aligned, because we want hot data to be located
207210 // in a single cache line if possible (it's accessed in every interceptor).
208 ALIGNED(64) LibIgnore libignore;
211 alignas(64) LibIgnore libignore;
209212 __sanitizer_sigaction sigactions[kSigCount];
210213#if !SANITIZER_APPLE && !SANITIZER_NETBSD
211214 unsigned finalize_key;
......@@ -217,7 +220,7 @@ struct InterceptorContext {
217220 InterceptorContext() : libignore(LINKER_INITIALIZED), atexit_mu(MutexTypeAtExit), AtExitStack() {}
218221};
219222
220static ALIGNED(64) char interceptor_placeholder[sizeof(InterceptorContext)];
223alignas(64) static char interceptor_placeholder[sizeof(InterceptorContext)];
221224InterceptorContext *interceptor_ctx() {
222225 return reinterpret_cast<InterceptorContext*>(&interceptor_placeholder[0]);
223226}
......@@ -1085,7 +1088,18 @@ TSAN_INTERCEPTOR(int, pthread_join, void *th, void **ret) {
10851088 return res;
10861089}
10871090
1088DEFINE_REAL_PTHREAD_FUNCTIONS
1091// DEFINE_INTERNAL_PTHREAD_FUNCTIONS
1092namespace __sanitizer {
1093int internal_pthread_create(void *th, void *attr, void *(*callback)(void *),
1094 void *param) {
1095 ScopedIgnoreInterceptors ignore;
1096 return REAL(pthread_create)(th, attr, callback, param);
1097}
1098int internal_pthread_join(void *th, void **ret) {
1099 ScopedIgnoreInterceptors ignore;
1100 return REAL(pthread_join(th, ret));
1101}
1102} // namespace __sanitizer
10891103
10901104TSAN_INTERCEPTOR(int, pthread_detach, void *th) {
10911105 SCOPED_INTERCEPTOR_RAW(pthread_detach, th);
......@@ -1338,7 +1352,7 @@ TSAN_INTERCEPTOR(int, pthread_mutex_destroy, void *m) {
13381352TSAN_INTERCEPTOR(int, pthread_mutex_lock, void *m) {
13391353 SCOPED_TSAN_INTERCEPTOR(pthread_mutex_lock, m);
13401354 MutexPreLock(thr, pc, (uptr)m);
1341 int res = REAL(pthread_mutex_lock)(m);
1355 int res = BLOCK_REAL(pthread_mutex_lock)(m);
13421356 if (res == errno_EOWNERDEAD)
13431357 MutexRepair(thr, pc, (uptr)m);
13441358 if (res == 0 || res == errno_EOWNERDEAD)
......@@ -1378,6 +1392,22 @@ TSAN_INTERCEPTOR(int, pthread_mutex_unlock, void *m) {
13781392 return res;
13791393}
13801394
1395#if SANITIZER_LINUX
1396TSAN_INTERCEPTOR(int, pthread_mutex_clocklock, void *m,
1397 __sanitizer_clockid_t clock, void *abstime) {
1398 SCOPED_TSAN_INTERCEPTOR(pthread_mutex_clocklock, m, clock, abstime);
1399 MutexPreLock(thr, pc, (uptr)m);
1400 int res = BLOCK_REAL(pthread_mutex_clocklock)(m, clock, abstime);
1401 if (res == errno_EOWNERDEAD)
1402 MutexRepair(thr, pc, (uptr)m);
1403 if (res == 0 || res == errno_EOWNERDEAD)
1404 MutexPostLock(thr, pc, (uptr)m);
1405 if (res == errno_EINVAL)
1406 MutexInvalidAccess(thr, pc, (uptr)m);
1407 return res;
1408}
1409#endif
1410
13811411#if SANITIZER_GLIBC
13821412# if !__GLIBC_PREREQ(2, 34)
13831413// glibc 2.34 applies a non-default version for the two functions. They are no
......@@ -1385,7 +1415,7 @@ TSAN_INTERCEPTOR(int, pthread_mutex_unlock, void *m) {
13851415TSAN_INTERCEPTOR(int, __pthread_mutex_lock, void *m) {
13861416 SCOPED_TSAN_INTERCEPTOR(__pthread_mutex_lock, m);
13871417 MutexPreLock(thr, pc, (uptr)m);
1388 int res = REAL(__pthread_mutex_lock)(m);
1418 int res = BLOCK_REAL(__pthread_mutex_lock)(m);
13891419 if (res == errno_EOWNERDEAD)
13901420 MutexRepair(thr, pc, (uptr)m);
13911421 if (res == 0 || res == errno_EOWNERDEAD)
......@@ -1428,7 +1458,7 @@ TSAN_INTERCEPTOR(int, pthread_spin_destroy, void *m) {
14281458TSAN_INTERCEPTOR(int, pthread_spin_lock, void *m) {
14291459 SCOPED_TSAN_INTERCEPTOR(pthread_spin_lock, m);
14301460 MutexPreLock(thr, pc, (uptr)m);
1431 int res = REAL(pthread_spin_lock)(m);
1461 int res = BLOCK_REAL(pthread_spin_lock)(m);
14321462 if (res == 0) {
14331463 MutexPostLock(thr, pc, (uptr)m);
14341464 }
......@@ -1503,7 +1533,7 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_timedrdlock, void *m, void *abstime) {
15031533TSAN_INTERCEPTOR(int, pthread_rwlock_wrlock, void *m) {
15041534 SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_wrlock, m);
15051535 MutexPreLock(thr, pc, (uptr)m);
1506 int res = REAL(pthread_rwlock_wrlock)(m);
1536 int res = BLOCK_REAL(pthread_rwlock_wrlock)(m);
15071537 if (res == 0) {
15081538 MutexPostLock(thr, pc, (uptr)m);
15091539 }
......@@ -1595,47 +1625,40 @@ TSAN_INTERCEPTOR(int, __fxstat, int version, int fd, void *buf) {
15951625 FdAccess(thr, pc, fd);
15961626 return REAL(__fxstat)(version, fd, buf);
15971627}
1598#define TSAN_MAYBE_INTERCEPT___FXSTAT TSAN_INTERCEPT(__fxstat)
1628
1629TSAN_INTERCEPTOR(int, __fxstat64, int version, int fd, void *buf) {
1630 SCOPED_TSAN_INTERCEPTOR(__fxstat64, version, fd, buf);
1631 if (fd > 0)
1632 FdAccess(thr, pc, fd);
1633 return REAL(__fxstat64)(version, fd, buf);
1634}
1635#define TSAN_MAYBE_INTERCEPT___FXSTAT TSAN_INTERCEPT(__fxstat); TSAN_INTERCEPT(__fxstat64)
15991636#else
16001637#define TSAN_MAYBE_INTERCEPT___FXSTAT
16011638#endif
16021639
1640#if !SANITIZER_GLIBC || __GLIBC_PREREQ(2, 33)
16031641TSAN_INTERCEPTOR(int, fstat, int fd, void *buf) {
1604#if SANITIZER_GLIBC
1605 SCOPED_TSAN_INTERCEPTOR(__fxstat, 0, fd, buf);
1606 if (fd > 0)
1607 FdAccess(thr, pc, fd);
1608 return REAL(__fxstat)(0, fd, buf);
1609#else
16101642 SCOPED_TSAN_INTERCEPTOR(fstat, fd, buf);
16111643 if (fd > 0)
16121644 FdAccess(thr, pc, fd);
16131645 return REAL(fstat)(fd, buf);
1614#endif
1615}
1616
1617#if SANITIZER_GLIBC
1618TSAN_INTERCEPTOR(int, __fxstat64, int version, int fd, void *buf) {
1619 SCOPED_TSAN_INTERCEPTOR(__fxstat64, version, fd, buf);
1620 if (fd > 0)
1621 FdAccess(thr, pc, fd);
1622 return REAL(__fxstat64)(version, fd, buf);
16231646}
1624#define TSAN_MAYBE_INTERCEPT___FXSTAT64 TSAN_INTERCEPT(__fxstat64)
1647# define TSAN_MAYBE_INTERCEPT_FSTAT TSAN_INTERCEPT(fstat)
16251648#else
1626#define TSAN_MAYBE_INTERCEPT___FXSTAT64
1649# define TSAN_MAYBE_INTERCEPT_FSTAT
16271650#endif
16281651
1629#if SANITIZER_GLIBC
1652#if __GLIBC_PREREQ(2, 33)
16301653TSAN_INTERCEPTOR(int, fstat64, int fd, void *buf) {
1631 SCOPED_TSAN_INTERCEPTOR(__fxstat64, 0, fd, buf);
1654 SCOPED_TSAN_INTERCEPTOR(fstat64, fd, buf);
16321655 if (fd > 0)
16331656 FdAccess(thr, pc, fd);
1634 return REAL(__fxstat64)(0, fd, buf);
1657 return REAL(fstat64)(fd, buf);
16351658}
1636#define TSAN_MAYBE_INTERCEPT_FSTAT64 TSAN_INTERCEPT(fstat64)
1659# define TSAN_MAYBE_INTERCEPT_FSTAT64 TSAN_INTERCEPT(fstat64)
16371660#else
1638#define TSAN_MAYBE_INTERCEPT_FSTAT64
1661# define TSAN_MAYBE_INTERCEPT_FSTAT64
16391662#endif
16401663
16411664TSAN_INTERCEPTOR(int, open, const char *name, int oflag, ...) {
......@@ -2565,7 +2588,7 @@ int sigaction_impl(int sig, const __sanitizer_sigaction *act,
25652588 // Copy act into sigactions[sig].
25662589 // Can't use struct copy, because compiler can emit call to memcpy.
25672590 // Can't use internal_memcpy, because it copies byte-by-byte,
2568 // and signal handler reads the handler concurrently. It it can read
2591 // and signal handler reads the handler concurrently. It can read
25692592 // some bytes from old value and some bytes from new value.
25702593 // Use volatile to prevent insertion of memcpy.
25712594 sigactions[sig].handler =
......@@ -2655,6 +2678,25 @@ static USED void syscall_fd_release(uptr pc, int fd) {
26552678 FdRelease(thr, pc, fd);
26562679}
26572680
2681static USED void sycall_blocking_start() {
2682 DPrintf("sycall_blocking_start()\n");
2683 ThreadState *thr = cur_thread();
2684 EnterBlockingFunc(thr);
2685 // When we are in a "blocking call", we process signals asynchronously
2686 // (right when they arrive). In this context we do not expect to be
2687 // executing any user/runtime code. The known interceptor sequence when
2688 // this is not true is: pthread_join -> munmap(stack). It's fine
2689 // to ignore munmap in this case -- we handle stack shadow separately.
2690 thr->ignore_interceptors++;
2691}
2692
2693static USED void sycall_blocking_end() {
2694 DPrintf("sycall_blocking_end()\n");
2695 ThreadState *thr = cur_thread();
2696 thr->ignore_interceptors--;
2697 atomic_store(&thr->in_blocking_func, 0, memory_order_relaxed);
2698}
2699
26582700static void syscall_pre_fork(uptr pc) { ForkBefore(cur_thread(), pc); }
26592701
26602702static void syscall_post_fork(uptr pc, int pid) {
......@@ -2709,6 +2751,9 @@ static void syscall_post_fork(uptr pc, int pid) {
27092751#define COMMON_SYSCALL_POST_FORK(res) \
27102752 syscall_post_fork(GET_CALLER_PC(), res)
27112753
2754#define COMMON_SYSCALL_BLOCKING_START() sycall_blocking_start()
2755#define COMMON_SYSCALL_BLOCKING_END() sycall_blocking_end()
2756
27122757#include "sanitizer_common/sanitizer_common_syscalls.inc"
27132758#include "sanitizer_common/sanitizer_syscalls_netbsd.inc"
27142759
......@@ -2843,8 +2888,21 @@ void InitializeInterceptors() {
28432888 REAL(memcpy) = internal_memcpy;
28442889#endif
28452890
2891 __interception::DoesNotSupportStaticLinking();
2892
28462893 new(interceptor_ctx()) InterceptorContext();
28472894
2895 // Interpose __tls_get_addr before the common interposers. This is needed
2896 // because dlsym() may call malloc on failure which could result in other
2897 // interposed functions being called that could eventually make use of TLS.
2898#ifdef NEED_TLS_GET_ADDR
2899# if !SANITIZER_S390
2900 TSAN_INTERCEPT(__tls_get_addr);
2901# else
2902 TSAN_INTERCEPT(__tls_get_addr_internal);
2903 TSAN_INTERCEPT(__tls_get_offset);
2904# endif
2905#endif
28482906 InitializeCommonInterceptors();
28492907 InitializeSignalInterceptors();
28502908 InitializeLibdispatchInterceptors();
......@@ -2900,6 +2958,9 @@ void InitializeInterceptors() {
29002958 TSAN_INTERCEPT(pthread_mutex_trylock);
29012959 TSAN_INTERCEPT(pthread_mutex_timedlock);
29022960 TSAN_INTERCEPT(pthread_mutex_unlock);
2961#if SANITIZER_LINUX
2962 TSAN_INTERCEPT(pthread_mutex_clocklock);
2963#endif
29032964#if SANITIZER_GLIBC
29042965# if !__GLIBC_PREREQ(2, 34)
29052966 TSAN_INTERCEPT(__pthread_mutex_lock);
......@@ -2929,10 +2990,9 @@ void InitializeInterceptors() {
29292990
29302991 TSAN_INTERCEPT(pthread_once);
29312992
2932 TSAN_INTERCEPT(fstat);
29332993 TSAN_MAYBE_INTERCEPT___FXSTAT;
2994 TSAN_MAYBE_INTERCEPT_FSTAT;
29342995 TSAN_MAYBE_INTERCEPT_FSTAT64;
2935 TSAN_MAYBE_INTERCEPT___FXSTAT64;
29362996 TSAN_INTERCEPT(open);
29372997 TSAN_MAYBE_INTERCEPT_OPEN64;
29382998 TSAN_INTERCEPT(creat);
......@@ -2989,15 +3049,6 @@ void InitializeInterceptors() {
29893049 TSAN_INTERCEPT(__cxa_atexit);
29903050 TSAN_INTERCEPT(_exit);
29913051
2992#ifdef NEED_TLS_GET_ADDR
2993#if !SANITIZER_S390
2994 TSAN_INTERCEPT(__tls_get_addr);
2995#else
2996 TSAN_INTERCEPT(__tls_get_addr_internal);
2997 TSAN_INTERCEPT(__tls_get_offset);
2998#endif
2999#endif
3000
30013052 TSAN_MAYBE_INTERCEPT__LWP_EXIT;
30023053 TSAN_MAYBE_INTERCEPT_THR_EXIT;
30033054
lib/tsan/tsan_interface.h+8
......@@ -419,6 +419,14 @@ void __tsan_go_atomic32_fetch_add(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
419419SANITIZER_INTERFACE_ATTRIBUTE
420420void __tsan_go_atomic64_fetch_add(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
421421SANITIZER_INTERFACE_ATTRIBUTE
422void __tsan_go_atomic32_fetch_and(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
423SANITIZER_INTERFACE_ATTRIBUTE
424void __tsan_go_atomic64_fetch_and(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
425SANITIZER_INTERFACE_ATTRIBUTE
426void __tsan_go_atomic32_fetch_or(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
427SANITIZER_INTERFACE_ATTRIBUTE
428void __tsan_go_atomic64_fetch_or(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
429SANITIZER_INTERFACE_ATTRIBUTE
422430void __tsan_go_atomic32_exchange(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
423431SANITIZER_INTERFACE_ATTRIBUTE
424432void __tsan_go_atomic64_exchange(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
lib/tsan/tsan_interface_ann.cpp+23-1
......@@ -76,7 +76,7 @@ struct DynamicAnnContext {
7676};
7777
7878static DynamicAnnContext *dyn_ann_ctx;
79static char dyn_ann_ctx_placeholder[sizeof(DynamicAnnContext)] ALIGNED(64);
79alignas(64) static char dyn_ann_ctx_placeholder[sizeof(DynamicAnnContext)];
8080
8181static void AddExpectRace(ExpectRace *list,
8282 char *f, int l, uptr addr, uptr size, char *desc) {
......@@ -435,4 +435,26 @@ void __tsan_mutex_post_divert(void *addr, unsigned flagz) {
435435 ThreadIgnoreBegin(thr, 0);
436436 ThreadIgnoreSyncBegin(thr, 0);
437437}
438
439static void ReportMutexHeldWrongContext(ThreadState *thr, uptr pc) {
440 ThreadRegistryLock l(&ctx->thread_registry);
441 ScopedReport rep(ReportTypeMutexHeldWrongContext);
442 for (uptr i = 0; i < thr->mset.Size(); ++i) {
443 MutexSet::Desc desc = thr->mset.Get(i);
444 rep.AddMutex(desc.addr, desc.stack_id);
445 }
446 VarSizeStackTrace trace;
447 ObtainCurrentStack(thr, pc, &trace);
448 rep.AddStack(trace, true);
449 OutputReport(thr, rep);
450}
451
452INTERFACE_ATTRIBUTE
453void __tsan_check_no_mutexes_held() {
454 SCOPED_ANNOTATION(__tsan_check_no_mutexes_held);
455 if (thr->mset.Size() == 0) {
456 return;
457 }
458 ReportMutexHeldWrongContext(thr, pc);
459}
438460} // extern "C"
lib/tsan/tsan_interface_atomic.cpp+24
......@@ -894,6 +894,30 @@ void __tsan_go_atomic64_fetch_add(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
894894 ATOMIC_RET(FetchAdd, *(a64*)(a+16), *(a64**)a, *(a64*)(a+8), mo_acq_rel);
895895}
896896
897SANITIZER_INTERFACE_ATTRIBUTE
898void __tsan_go_atomic32_fetch_and(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
899 ATOMIC_RET(FetchAnd, *(a32 *)(a + 16), *(a32 **)a, *(a32 *)(a + 8),
900 mo_acq_rel);
901}
902
903SANITIZER_INTERFACE_ATTRIBUTE
904void __tsan_go_atomic64_fetch_and(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
905 ATOMIC_RET(FetchAnd, *(a64 *)(a + 16), *(a64 **)a, *(a64 *)(a + 8),
906 mo_acq_rel);
907}
908
909SANITIZER_INTERFACE_ATTRIBUTE
910void __tsan_go_atomic32_fetch_or(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
911 ATOMIC_RET(FetchOr, *(a32 *)(a + 16), *(a32 **)a, *(a32 *)(a + 8),
912 mo_acq_rel);
913}
914
915SANITIZER_INTERFACE_ATTRIBUTE
916void __tsan_go_atomic64_fetch_or(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
917 ATOMIC_RET(FetchOr, *(a64 *)(a + 16), *(a64 **)a, *(a64 *)(a + 8),
918 mo_acq_rel);
919}
920
897921SANITIZER_INTERFACE_ATTRIBUTE
898922void __tsan_go_atomic32_exchange(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
899923 ATOMIC_RET(Exchange, *(a32*)(a+16), *(a32**)a, *(a32*)(a+8), mo_acq_rel);
lib/tsan/tsan_mman.cpp+20-9
......@@ -9,17 +9,19 @@
99// This file is a part of ThreadSanitizer (TSan), a race detector.
1010//
1111//===----------------------------------------------------------------------===//
12#include "tsan_mman.h"
13
1214#include "sanitizer_common/sanitizer_allocator_checks.h"
1315#include "sanitizer_common/sanitizer_allocator_interface.h"
1416#include "sanitizer_common/sanitizer_allocator_report.h"
1517#include "sanitizer_common/sanitizer_common.h"
1618#include "sanitizer_common/sanitizer_errno.h"
1719#include "sanitizer_common/sanitizer_placement_new.h"
20#include "sanitizer_common/sanitizer_stackdepot.h"
21#include "tsan_flags.h"
1822#include "tsan_interface.h"
19#include "tsan_mman.h"
20#include "tsan_rtl.h"
2123#include "tsan_report.h"
22#include "tsan_flags.h"
24#include "tsan_rtl.h"
2325
2426namespace __tsan {
2527
......@@ -52,7 +54,7 @@ struct MapUnmapCallback {
5254 }
5355};
5456
55static char allocator_placeholder[sizeof(Allocator)] ALIGNED(64);
57alignas(64) static char allocator_placeholder[sizeof(Allocator)];
5658Allocator *allocator() {
5759 return reinterpret_cast<Allocator*>(&allocator_placeholder);
5860}
......@@ -73,7 +75,7 @@ struct GlobalProc {
7375 internal_alloc_mtx(MutexTypeInternalAlloc) {}
7476};
7577
76static char global_proc_placeholder[sizeof(GlobalProc)] ALIGNED(64);
78alignas(64) static char global_proc_placeholder[sizeof(GlobalProc)];
7779GlobalProc *global_proc() {
7880 return reinterpret_cast<GlobalProc*>(&global_proc_placeholder);
7981}
......@@ -115,12 +117,21 @@ ScopedGlobalProcessor::~ScopedGlobalProcessor() {
115117 gp->mtx.Unlock();
116118}
117119
118void AllocatorLock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
120void AllocatorLockBeforeFork() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
119121 global_proc()->internal_alloc_mtx.Lock();
120122 InternalAllocatorLock();
121}
122
123void AllocatorUnlock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
123#if !SANITIZER_APPLE
124 // OS X allocates from hooks, see 6a3958247a.
125 allocator()->ForceLock();
126 StackDepotLockBeforeFork();
127#endif
128}
129
130void AllocatorUnlockAfterFork(bool child) SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
131#if !SANITIZER_APPLE
132 StackDepotUnlockAfterFork(child);
133 allocator()->ForceUnlock();
134#endif
124135 InternalAllocatorUnlock();
125136 global_proc()->internal_alloc_mtx.Unlock();
126137}
lib/tsan/tsan_mman.h+2-2
......@@ -24,8 +24,8 @@ void ReplaceSystemMalloc();
2424void AllocatorProcStart(Processor *proc);
2525void AllocatorProcFinish(Processor *proc);
2626void AllocatorPrintStats();
27void AllocatorLock();
28void AllocatorUnlock();
27void AllocatorLockBeforeFork();
28void AllocatorUnlockAfterFork(bool child);
2929void GlobalProcessorLock();
3030void GlobalProcessorUnlock();
3131
lib/tsan/tsan_platform.h+128-23
......@@ -46,17 +46,16 @@ enum {
4646
4747/*
4848C/C++ on linux/x86_64 and freebsd/x86_64
490000 0000 1000 - 0080 0000 0000: main binary and/or MAP_32BIT mappings (512GB)
500040 0000 0000 - 0100 0000 0000: -
510100 0000 0000 - 1000 0000 0000: shadow
521000 0000 0000 - 3000 0000 0000: -
533000 0000 0000 - 3400 0000 0000: metainfo (memory blocks and sync objects)
543400 0000 0000 - 5500 0000 0000: -
555500 0000 0000 - 5680 0000 0000: pie binaries without ASLR or on 4.1+ kernels
565680 0000 0000 - 7d00 0000 0000: -
577b00 0000 0000 - 7c00 0000 0000: heap
587c00 0000 0000 - 7e80 0000 0000: -
597e80 0000 0000 - 8000 0000 0000: modules and main thread stack
490000 0000 1000 - 0200 0000 0000: main binary and/or MAP_32BIT mappings (2TB)
500200 0000 0000 - 1000 0000 0000: -
511000 0000 0000 - 3000 0000 0000: shadow (32TB)
523000 0000 0000 - 3800 0000 0000: metainfo (memory blocks and sync objects; 8TB)
533800 0000 0000 - 5500 0000 0000: -
545500 0000 0000 - 5a00 0000 0000: pie binaries without ASLR or on 4.1+ kernels
555a00 0000 0000 - 7200 0000 0000: -
567200 0000 0000 - 7300 0000 0000: heap (1TB)
577300 0000 0000 - 7a00 0000 0000: -
587a00 0000 0000 - 8000 0000 0000: modules and main thread stack (6TB)
6059
6160C/C++ on netbsd/amd64 can reuse the same mapping:
6261 * The address space starts from 0x1000 (option with 0x0) and ends with
......@@ -72,20 +71,20 @@ C/C++ on netbsd/amd64 can reuse the same mapping:
7271*/
7372struct Mapping48AddressSpace {
7473 static const uptr kMetaShadowBeg = 0x300000000000ull;
75 static const uptr kMetaShadowEnd = 0x340000000000ull;
76 static const uptr kShadowBeg = 0x010000000000ull;
77 static const uptr kShadowEnd = 0x100000000000ull;
78 static const uptr kHeapMemBeg = 0x7b0000000000ull;
79 static const uptr kHeapMemEnd = 0x7c0000000000ull;
74 static const uptr kMetaShadowEnd = 0x380000000000ull;
75 static const uptr kShadowBeg = 0x100000000000ull;
76 static const uptr kShadowEnd = 0x300000000000ull;
77 static const uptr kHeapMemBeg = 0x720000000000ull;
78 static const uptr kHeapMemEnd = 0x730000000000ull;
8079 static const uptr kLoAppMemBeg = 0x000000001000ull;
81 static const uptr kLoAppMemEnd = 0x008000000000ull;
80 static const uptr kLoAppMemEnd = 0x020000000000ull;
8281 static const uptr kMidAppMemBeg = 0x550000000000ull;
83 static const uptr kMidAppMemEnd = 0x568000000000ull;
84 static const uptr kHiAppMemBeg = 0x7e8000000000ull;
82 static const uptr kMidAppMemEnd = 0x5a0000000000ull;
83 static const uptr kHiAppMemBeg = 0x7a0000000000ull;
8584 static const uptr kHiAppMemEnd = 0x800000000000ull;
86 static const uptr kShadowMsk = 0x780000000000ull;
87 static const uptr kShadowXor = 0x040000000000ull;
88 static const uptr kShadowAdd = 0x000000000000ull;
85 static const uptr kShadowMsk = 0x700000000000ull;
86 static const uptr kShadowXor = 0x000000000000ull;
87 static const uptr kShadowAdd = 0x100000000000ull;
8988 static const uptr kVdsoBeg = 0xf000000000000000ull;
9089};
9190
......@@ -377,6 +376,71 @@ struct MappingPPC64_47 {
377376 static const uptr kMidAppMemEnd = 0;
378377};
379378
379/*
380C/C++ on linux/riscv64 (39-bit VMA)
3810000 0010 00 - 0200 0000 00: main binary ( 8 GB)
3820200 0000 00 - 1000 0000 00: -
3831000 0000 00 - 4000 0000 00: shadow memory (64 GB)
3844000 0000 00 - 4800 0000 00: metainfo (16 GB)
3854800 0000 00 - 5500 0000 00: -
3865500 0000 00 - 5a00 0000 00: main binary (PIE) (~8 GB)
3875600 0000 00 - 7c00 0000 00: -
3887d00 0000 00 - 7fff ffff ff: libraries and main thread stack ( 8 GB)
389
390mmap by default allocates from top downwards
391VDSO sits below loader and above dynamic libraries, within HiApp region.
392Heap starts after program region whose position depends on pie or non-pie.
393Disable tracking them since their locations are not fixed.
394*/
395struct MappingRiscv64_39 {
396 static const uptr kLoAppMemBeg = 0x0000001000ull;
397 static const uptr kLoAppMemEnd = 0x0200000000ull;
398 static const uptr kShadowBeg = 0x1000000000ull;
399 static const uptr kShadowEnd = 0x2000000000ull;
400 static const uptr kMetaShadowBeg = 0x2000000000ull;
401 static const uptr kMetaShadowEnd = 0x2400000000ull;
402 static const uptr kMidAppMemBeg = 0x2aaaaaa000ull;
403 static const uptr kMidAppMemEnd = 0x2c00000000ull;
404 static const uptr kHeapMemBeg = 0x2c00000000ull;
405 static const uptr kHeapMemEnd = 0x2c00000000ull;
406 static const uptr kHiAppMemBeg = 0x3c00000000ull;
407 static const uptr kHiAppMemEnd = 0x3fffffffffull;
408 static const uptr kShadowMsk = 0x3800000000ull;
409 static const uptr kShadowXor = 0x0800000000ull;
410 static const uptr kShadowAdd = 0x0000000000ull;
411 static const uptr kVdsoBeg = 0x4000000000ull;
412};
413
414/*
415C/C++ on linux/riscv64 (48-bit VMA)
4160000 0000 1000 - 0400 0000 0000: main binary ( 4 TB)
4170500 0000 0000 - 2000 0000 0000: -
4182000 0000 0000 - 4000 0000 0000: shadow memory (32 TB)
4194000 0000 0000 - 4800 0000 0000: metainfo ( 8 TB)
4204800 0000 0000 - 5555 5555 5000: -
4215555 5555 5000 - 5a00 0000 0000: main binary (PIE) (~5 TB)
4225a00 0000 0000 - 7a00 0000 0000: -
4237a00 0000 0000 - 7fff ffff ffff: libraries and main thread stack ( 6 TB)
424*/
425struct MappingRiscv64_48 {
426 static const uptr kLoAppMemBeg = 0x000000001000ull;
427 static const uptr kLoAppMemEnd = 0x040000000000ull;
428 static const uptr kShadowBeg = 0x200000000000ull;
429 static const uptr kShadowEnd = 0x400000000000ull;
430 static const uptr kMetaShadowBeg = 0x400000000000ull;
431 static const uptr kMetaShadowEnd = 0x480000000000ull;
432 static const uptr kMidAppMemBeg = 0x555555555000ull;
433 static const uptr kMidAppMemEnd = 0x5a0000000000ull;
434 static const uptr kHeapMemBeg = 0x5a0000000000ull;
435 static const uptr kHeapMemEnd = 0x5a0000000000ull;
436 static const uptr kHiAppMemBeg = 0x7a0000000000ull;
437 static const uptr kHiAppMemEnd = 0x7fffffffffffull;
438 static const uptr kShadowMsk = 0x700000000000ull;
439 static const uptr kShadowXor = 0x100000000000ull;
440 static const uptr kShadowAdd = 0x000000000000ull;
441 static const uptr kVdsoBeg = 0x800000000000ull;
442};
443
380444/*
381445C/C++ on linux/s390x
382446While the kernel provides a 64-bit address space, we have to restrict ourselves
......@@ -558,6 +622,35 @@ struct MappingGoAarch64 {
558622 static const uptr kShadowAdd = 0x200000000000ull;
559623};
560624
625/* Go on linux/loongarch64 (47-bit VMA)
6260000 0000 1000 - 0000 1000 0000: executable
6270000 1000 0000 - 00c0 0000 0000: -
62800c0 0000 0000 - 00e0 0000 0000: heap
62900e0 0000 0000 - 2000 0000 0000: -
6302000 0000 0000 - 2800 0000 0000: shadow
6312800 0000 0000 - 3000 0000 0000: -
6323000 0000 0000 - 3200 0000 0000: metainfo (memory blocks and sync objects)
6333200 0000 0000 - 8000 0000 0000: -
634*/
635struct MappingGoLoongArch64_47 {
636 static const uptr kMetaShadowBeg = 0x300000000000ull;
637 static const uptr kMetaShadowEnd = 0x320000000000ull;
638 static const uptr kShadowBeg = 0x200000000000ull;
639 static const uptr kShadowEnd = 0x280000000000ull;
640 static const uptr kLoAppMemBeg = 0x000000001000ull;
641 static const uptr kLoAppMemEnd = 0x00e000000000ull;
642 static const uptr kMidAppMemBeg = 0;
643 static const uptr kMidAppMemEnd = 0;
644 static const uptr kHiAppMemBeg = 0;
645 static const uptr kHiAppMemEnd = 0;
646 static const uptr kHeapMemBeg = 0;
647 static const uptr kHeapMemEnd = 0;
648 static const uptr kVdsoBeg = 0;
649 static const uptr kShadowMsk = 0;
650 static const uptr kShadowXor = 0;
651 static const uptr kShadowAdd = 0x200000000000ull;
652};
653
561654/*
562655Go on linux/mips64 (47-bit VMA)
5636560000 0000 1000 - 0000 1000 0000: executable
......@@ -633,6 +726,8 @@ ALWAYS_INLINE auto SelectMapping(Arg arg) {
633726 return Func::template Apply<MappingGoS390x>(arg);
634727# elif defined(__aarch64__)
635728 return Func::template Apply<MappingGoAarch64>(arg);
729# elif defined(__loongarch_lp64)
730 return Func::template Apply<MappingGoLoongArch64_47>(arg);
636731# elif SANITIZER_WINDOWS
637732 return Func::template Apply<MappingGoWindows>(arg);
638733# else
......@@ -665,6 +760,13 @@ ALWAYS_INLINE auto SelectMapping(Arg arg) {
665760 }
666761# elif defined(__mips64)
667762 return Func::template Apply<MappingMips64_40>(arg);
763# elif SANITIZER_RISCV64
764 switch (vmaSize) {
765 case 39:
766 return Func::template Apply<MappingRiscv64_39>(arg);
767 case 48:
768 return Func::template Apply<MappingRiscv64_48>(arg);
769 }
668770# elif defined(__s390x__)
669771 return Func::template Apply<MappingS390x>(arg);
670772# else
......@@ -686,12 +788,15 @@ void ForEachMapping() {
686788 Func::template Apply<MappingPPC64_44>();
687789 Func::template Apply<MappingPPC64_46>();
688790 Func::template Apply<MappingPPC64_47>();
791 Func::template Apply<MappingRiscv64_39>();
792 Func::template Apply<MappingRiscv64_48>();
689793 Func::template Apply<MappingS390x>();
690794 Func::template Apply<MappingGo48>();
691795 Func::template Apply<MappingGoWindows>();
692796 Func::template Apply<MappingGoPPC64_46>();
693797 Func::template Apply<MappingGoPPC64_47>();
694798 Func::template Apply<MappingGoAarch64>();
799 Func::template Apply<MappingGoLoongArch64_47>();
695800 Func::template Apply<MappingGoMips64_47>();
696801 Func::template Apply<MappingGoS390x>();
697802}
......@@ -919,7 +1024,7 @@ inline uptr RestoreAddr(uptr addr) {
9191024
9201025void InitializePlatform();
9211026void InitializePlatformEarly();
922void CheckAndProtect();
1027bool CheckAndProtect(bool protect, bool ignore_heap, bool print_warnings);
9231028void InitializeShadowMemoryPlatform();
9241029void WriteMemoryProfile(char *buf, uptr buf_size, u64 uptime_ns);
9251030int ExtractResolvFDs(void *state, int *fds, int nfd);
lib/tsan/tsan_platform_linux.cpp+159-61
......@@ -152,7 +152,7 @@ void WriteMemoryProfile(char *buf, uptr buf_size, u64 uptime_ns) {
152152#if !SANITIZER_GO
153153// Mark shadow for .rodata sections with the special Shadow::kRodata marker.
154154// Accesses to .rodata can't race, so this saves time, memory and trace space.
155static void MapRodata() {
155static NOINLINE void MapRodata(char* buffer, uptr size) {
156156 // First create temp file.
157157 const char *tmpdir = GetEnv("TMPDIR");
158158 if (tmpdir == 0)
......@@ -163,13 +163,12 @@ static void MapRodata() {
163163#endif
164164 if (tmpdir == 0)
165165 return;
166 char name[256];
167 internal_snprintf(name, sizeof(name), "%s/tsan.rodata.%d",
166 internal_snprintf(buffer, size, "%s/tsan.rodata.%d",
168167 tmpdir, (int)internal_getpid());
169 uptr openrv = internal_open(name, O_RDWR | O_CREAT | O_EXCL, 0600);
168 uptr openrv = internal_open(buffer, O_RDWR | O_CREAT | O_EXCL, 0600);
170169 if (internal_iserror(openrv))
171170 return;
172 internal_unlink(name); // Unlink it now, so that we can reuse the buffer.
171 internal_unlink(buffer); // Unlink it now, so that we can reuse the buffer.
173172 fd_t fd = openrv;
174173 // Fill the file with Shadow::kRodata.
175174 const uptr kMarkerSize = 512 * 1024 / sizeof(RawShadow);
......@@ -188,8 +187,8 @@ static void MapRodata() {
188187 }
189188 // Map the file into shadow of .rodata sections.
190189 MemoryMappingLayout proc_maps(/*cache_enabled*/true);
191 // Reusing the buffer 'name'.
192 MemoryMappedSegment segment(name, ARRAY_SIZE(name));
190 // Reusing the buffer 'buffer'.
191 MemoryMappedSegment segment(buffer, size);
193192 while (proc_maps.Next(&segment)) {
194193 if (segment.filename[0] != 0 && segment.filename[0] != '[' &&
195194 segment.IsReadable() && segment.IsExecutable() &&
......@@ -209,11 +208,103 @@ static void MapRodata() {
209208}
210209
211210void InitializeShadowMemoryPlatform() {
212 MapRodata();
211 char buffer[256]; // Keep in a different frame.
212 MapRodata(buffer, sizeof(buffer));
213213}
214214
215215#endif // #if !SANITIZER_GO
216216
217# if !SANITIZER_GO
218static void ReExecIfNeeded(bool ignore_heap) {
219 // Go maps shadow memory lazily and works fine with limited address space.
220 // Unlimited stack is not a problem as well, because the executable
221 // is not compiled with -pie.
222 bool reexec = false;
223 // TSan doesn't play well with unlimited stack size (as stack
224 // overlaps with shadow memory). If we detect unlimited stack size,
225 // we re-exec the program with limited stack size as a best effort.
226 if (StackSizeIsUnlimited()) {
227 const uptr kMaxStackSize = 32 * 1024 * 1024;
228 VReport(1,
229 "Program is run with unlimited stack size, which wouldn't "
230 "work with ThreadSanitizer.\n"
231 "Re-execing with stack size limited to %zd bytes.\n",
232 kMaxStackSize);
233 SetStackSizeLimitInBytes(kMaxStackSize);
234 reexec = true;
235 }
236
237 if (!AddressSpaceIsUnlimited()) {
238 Report(
239 "WARNING: Program is run with limited virtual address space,"
240 " which wouldn't work with ThreadSanitizer.\n");
241 Report("Re-execing with unlimited virtual address space.\n");
242 SetAddressSpaceUnlimited();
243 reexec = true;
244 }
245
246# if SANITIZER_LINUX
247# if SANITIZER_ANDROID && (defined(__aarch64__) || defined(__x86_64__))
248 // ASLR personality check.
249 int old_personality = personality(0xffffffff);
250 bool aslr_on =
251 (old_personality != -1) && ((old_personality & ADDR_NO_RANDOMIZE) == 0);
252
253 // After patch "arm64: mm: support ARCH_MMAP_RND_BITS." is introduced in
254 // linux kernel, the random gap between stack and mapped area is increased
255 // from 128M to 36G on 39-bit aarch64. As it is almost impossible to cover
256 // this big range, we should disable randomized virtual space on aarch64.
257 if (aslr_on) {
258 VReport(1,
259 "WARNING: Program is run with randomized virtual address "
260 "space, which wouldn't work with ThreadSanitizer on Android.\n"
261 "Re-execing with fixed virtual address space.\n");
262 CHECK_NE(personality(old_personality | ADDR_NO_RANDOMIZE), -1);
263 reexec = true;
264 }
265# endif
266
267 if (reexec) {
268 // Don't check the address space since we're going to re-exec anyway.
269 } else if (!CheckAndProtect(false, ignore_heap, false)) {
270 // ASLR personality check.
271 // N.B. 'personality' is sometimes forbidden by sandboxes, so we only call
272 // this as a last resort (when the memory mapping is incompatible and TSan
273 // would fail anyway).
274 int old_personality = personality(0xffffffff);
275 bool aslr_on =
276 (old_personality != -1) && ((old_personality & ADDR_NO_RANDOMIZE) == 0);
277
278 if (aslr_on) {
279 // Disable ASLR if the memory layout was incompatible.
280 // Alternatively, we could just keep re-execing until we get lucky
281 // with a compatible randomized layout, but the risk is that if it's
282 // not an ASLR-related issue, we will be stuck in an infinite loop of
283 // re-execing (unless we change ReExec to pass a parameter of the
284 // number of retries allowed.)
285 VReport(1,
286 "WARNING: ThreadSanitizer: memory layout is incompatible, "
287 "possibly due to high-entropy ASLR.\n"
288 "Re-execing with fixed virtual address space.\n"
289 "N.B. reducing ASLR entropy is preferable.\n");
290 CHECK_NE(personality(old_personality | ADDR_NO_RANDOMIZE), -1);
291 reexec = true;
292 } else {
293 Printf(
294 "FATAL: ThreadSanitizer: memory layout is incompatible, "
295 "even though ASLR is disabled.\n"
296 "Please file a bug.\n");
297 DumpProcessMap();
298 Die();
299 }
300 }
301# endif // SANITIZER_LINUX
302
303 if (reexec)
304 ReExec();
305}
306# endif
307
217308void InitializePlatformEarly() {
218309 vmaSize =
219310 (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1);
......@@ -238,7 +329,13 @@ void InitializePlatformEarly() {
238329 Printf("FATAL: Found %zd - Supported 47\n", vmaSize);
239330 Die();
240331 }
241# endif
332# else
333 if (vmaSize != 47) {
334 Printf("FATAL: ThreadSanitizer: unsupported VMA range\n");
335 Printf("FATAL: Found %zd - Supported 47\n", vmaSize);
336 Die();
337 }
338# endif
242339#elif defined(__powerpc64__)
243340# if !SANITIZER_GO
244341 if (vmaSize != 44 && vmaSize != 46 && vmaSize != 47) {
......@@ -267,7 +364,22 @@ void InitializePlatformEarly() {
267364 Die();
268365 }
269366# endif
270#endif
367# elif SANITIZER_RISCV64
368 // the bottom half of vma is allocated for userspace
369 vmaSize = vmaSize + 1;
370# if !SANITIZER_GO
371 if (vmaSize != 39 && vmaSize != 48) {
372 Printf("FATAL: ThreadSanitizer: unsupported VMA range\n");
373 Printf("FATAL: Found %zd - Supported 39 and 48\n", vmaSize);
374 Die();
375 }
376# endif
377# endif
378
379# if !SANITIZER_GO
380 // Heap has not been allocated yet
381 ReExecIfNeeded(false);
382# endif
271383}
272384
273385void InitializePlatform() {
......@@ -278,52 +390,34 @@ void InitializePlatform() {
278390 // is not compiled with -pie.
279391#if !SANITIZER_GO
280392 {
281 bool reexec = false;
282 // TSan doesn't play well with unlimited stack size (as stack
283 // overlaps with shadow memory). If we detect unlimited stack size,
284 // we re-exec the program with limited stack size as a best effort.
285 if (StackSizeIsUnlimited()) {
286 const uptr kMaxStackSize = 32 * 1024 * 1024;
287 VReport(1, "Program is run with unlimited stack size, which wouldn't "
288 "work with ThreadSanitizer.\n"
289 "Re-execing with stack size limited to %zd bytes.\n",
290 kMaxStackSize);
291 SetStackSizeLimitInBytes(kMaxStackSize);
292 reexec = true;
293 }
294
295 if (!AddressSpaceIsUnlimited()) {
296 Report("WARNING: Program is run with limited virtual address space,"
297 " which wouldn't work with ThreadSanitizer.\n");
298 Report("Re-execing with unlimited virtual address space.\n");
299 SetAddressSpaceUnlimited();
300 reexec = true;
301 }
302#if SANITIZER_ANDROID && (defined(__aarch64__) || defined(__x86_64__))
303 // After patch "arm64: mm: support ARCH_MMAP_RND_BITS." is introduced in
304 // linux kernel, the random gap between stack and mapped area is increased
305 // from 128M to 36G on 39-bit aarch64. As it is almost impossible to cover
306 // this big range, we should disable randomized virtual space on aarch64.
307 // ASLR personality check.
308 int old_personality = personality(0xffffffff);
309 if (old_personality != -1 && (old_personality & ADDR_NO_RANDOMIZE) == 0) {
310 VReport(1, "WARNING: Program is run with randomized virtual address "
311 "space, which wouldn't work with ThreadSanitizer.\n"
312 "Re-execing with fixed virtual address space.\n");
313 CHECK_NE(personality(old_personality | ADDR_NO_RANDOMIZE), -1);
314 reexec = true;
315 }
316
317#endif
318#if SANITIZER_LINUX && (defined(__aarch64__) || defined(__loongarch_lp64))
393# if SANITIZER_LINUX && (defined(__aarch64__) || defined(__loongarch_lp64))
319394 // Initialize the xor key used in {sig}{set,long}jump.
320395 InitializeLongjmpXorKey();
321#endif
322 if (reexec)
323 ReExec();
396# endif
397 }
398
399 // We called ReExecIfNeeded() in InitializePlatformEarly(), but there are
400 // intervening allocations that result in an edge case:
401 // 1) InitializePlatformEarly(): memory layout is compatible
402 // 2) Intervening allocations happen
403 // 3) InitializePlatform(): memory layout is incompatible and fails
404 // CheckAndProtect()
405# if !SANITIZER_GO
406 // Heap has already been allocated
407 ReExecIfNeeded(true);
408# endif
409
410 // Earlier initialization steps already re-exec'ed until we got a compatible
411 // memory layout, so we don't expect any more issues here.
412 if (!CheckAndProtect(true, true, true)) {
413 Printf(
414 "FATAL: ThreadSanitizer: unexpectedly found incompatible memory "
415 "layout.\n");
416 Printf("FATAL: Please file a bug.\n");
417 DumpProcessMap();
418 Die();
324419 }
325420
326 CheckAndProtect();
327421 InitTlsSize();
328422#endif // !SANITIZER_GO
329423}
......@@ -399,13 +493,15 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) {
399493 return mangled_sp ^ xor_key;
400494#elif defined(__mips__)
401495 return mangled_sp;
402#elif defined(__s390x__)
496# elif SANITIZER_RISCV64
497 return mangled_sp;
498# elif defined(__s390x__)
403499 // tcbhead_t.stack_guard
404500 uptr xor_key = ((uptr *)__builtin_thread_pointer())[5];
405501 return mangled_sp ^ xor_key;
406#else
407 #error "Unknown platform"
408#endif
502# else
503# error "Unknown platform"
504# endif
409505}
410506
411507#if SANITIZER_NETBSD
......@@ -429,11 +525,13 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) {
429525# define LONG_JMP_SP_ENV_SLOT 1
430526# elif defined(__mips64)
431527# define LONG_JMP_SP_ENV_SLOT 1
432# elif defined(__s390x__)
433# define LONG_JMP_SP_ENV_SLOT 9
434# else
435# define LONG_JMP_SP_ENV_SLOT 6
436# endif
528# elif SANITIZER_RISCV64
529# define LONG_JMP_SP_ENV_SLOT 13
530# elif defined(__s390x__)
531# define LONG_JMP_SP_ENV_SLOT 9
532# else
533# define LONG_JMP_SP_ENV_SLOT 6
534# endif
437535#endif
438536
439537uptr ExtractLongJmpSp(uptr *env) {
lib/tsan/tsan_platform_mac.cpp+6-3
......@@ -46,8 +46,8 @@
4646namespace __tsan {
4747
4848#if !SANITIZER_GO
49static char main_thread_state[sizeof(ThreadState)] ALIGNED(
50 SANITIZER_CACHE_LINE_SIZE);
49alignas(SANITIZER_CACHE_LINE_SIZE) static char main_thread_state[sizeof(
50 ThreadState)];
5151static ThreadState *dead_thread_state;
5252static pthread_key_t thread_state_key;
5353
......@@ -239,7 +239,10 @@ static uptr longjmp_xor_key = 0;
239239void InitializePlatform() {
240240 DisableCoreDumperIfNecessary();
241241#if !SANITIZER_GO
242 CheckAndProtect();
242 if (!CheckAndProtect(true, true, true)) {
243 Printf("FATAL: ThreadSanitizer: found incompatible memory layout.\n");
244 Die();
245 }
243246
244247 InitializeThreadStateStorage();
245248
lib/tsan/tsan_platform_posix.cpp+37-6
......@@ -94,22 +94,51 @@ static void ProtectRange(uptr beg, uptr end) {
9494 }
9595}
9696
97void CheckAndProtect() {
97// CheckAndProtect will check if the memory layout is compatible with TSan.
98// Optionally (if 'protect' is true), it will set the memory regions between
99// app memory to be inaccessible.
100// 'ignore_heap' means it will not consider heap memory allocations to be a
101// conflict. Set this based on whether we are calling CheckAndProtect before
102// or after the allocator has initialized the heap.
103bool CheckAndProtect(bool protect, bool ignore_heap, bool print_warnings) {
98104 // Ensure that the binary is indeed compiled with -pie.
99105 MemoryMappingLayout proc_maps(true);
100106 MemoryMappedSegment segment;
101107 while (proc_maps.Next(&segment)) {
102 if (IsAppMem(segment.start)) continue;
108 if (segment.start >= HeapMemBeg() && segment.end <= HeapEnd()) {
109 if (ignore_heap) {
110 continue;
111 } else {
112 return false;
113 }
114 }
115
116 // Note: IsAppMem includes if it is heap memory, hence we must
117 // put this check after the heap bounds check.
118 if (IsAppMem(segment.start) && IsAppMem(segment.end - 1))
119 continue;
120
121 // Guard page after the heap end
103122 if (segment.start >= HeapMemEnd() && segment.start < HeapEnd()) continue;
123
104124 if (segment.protection == 0) // Zero page or mprotected.
105125 continue;
126
106127 if (segment.start >= VdsoBeg()) // vdso
107128 break;
108 Printf("FATAL: ThreadSanitizer: unexpected memory mapping 0x%zx-0x%zx\n",
109 segment.start, segment.end);
110 Die();
129
130 // Debug output can break tests. Suppress this message in most cases.
131 if (print_warnings)
132 Printf(
133 "WARNING: ThreadSanitizer: unexpected memory mapping 0x%zx-0x%zx\n",
134 segment.start, segment.end);
135
136 return false;
111137 }
112138
139 if (!protect)
140 return true;
141
113142# if SANITIZER_IOS && !SANITIZER_IOSSIM
114143 ProtectRange(HeapMemEnd(), ShadowBeg());
115144 ProtectRange(ShadowEnd(), MetaShadowBeg());
......@@ -135,8 +164,10 @@ void CheckAndProtect() {
135164 // Older s390x kernels may not support 5-level page tables.
136165 TryProtectRange(user_addr_max_l4, user_addr_max_l5);
137166#endif
167
168 return true;
138169}
139#endif
170# endif
140171
141172} // namespace __tsan
142173
lib/tsan/tsan_preinit.cpp+4-6
......@@ -16,11 +16,9 @@
1616
1717#if SANITIZER_CAN_USE_PREINIT_ARRAY
1818
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;
19// This section is linked into the main executable when -fsanitize=thread is
20// specified to perform initialization at a very early stage.
21__attribute__((section(".preinit_array"), used)) static auto preinit =
22 __tsan_init;
2523
2624#endif
lib/tsan/tsan_report.cpp+12-26
......@@ -93,7 +93,9 @@ static const char *ReportTypeString(ReportType typ, uptr tag) {
9393 return "signal handler spoils errno";
9494 case ReportTypeDeadlock:
9595 return "lock-order-inversion (potential deadlock)";
96 // No default case so compiler warns us if we miss one
96 case ReportTypeMutexHeldWrongContext:
97 return "mutex held in the wrong context";
98 // No default case so compiler warns us if we miss one
9799 }
98100 UNREACHABLE("missing case");
99101}
......@@ -106,10 +108,10 @@ void PrintStack(const ReportStack *ent) {
106108 SymbolizedStack *frame = ent->frames;
107109 for (int i = 0; frame && frame->info.address; frame = frame->next, i++) {
108110 InternalScopedString res;
109 RenderFrame(&res, common_flags()->stack_trace_format, i,
110 frame->info.address, &frame->info,
111 common_flags()->symbolize_vs_style,
112 common_flags()->strip_path_prefix);
111 StackTracePrinter::GetOrInit()->RenderFrame(
112 &res, common_flags()->stack_trace_format, i, frame->info.address,
113 &frame->info, common_flags()->symbolize_vs_style,
114 common_flags()->strip_path_prefix);
113115 Printf("%s\n", res.data());
114116 }
115117 Printf("\n");
......@@ -271,26 +273,10 @@ static ReportStack *ChooseSummaryStack(const ReportDesc *rep) {
271273 return 0;
272274}
273275
274static bool FrameIsInternal(const SymbolizedStack *frame) {
275 if (frame == 0)
276 return false;
277 const char *file = frame->info.file;
278 const char *module = frame->info.module;
279 if (file != 0 &&
280 (internal_strstr(file, "tsan_interceptors_posix.cpp") ||
281 internal_strstr(file, "tsan_interceptors_memintrinsics.cpp") ||
282 internal_strstr(file, "sanitizer_common_interceptors.inc") ||
283 internal_strstr(file, "tsan_interface_")))
284 return true;
285 if (module != 0 && (internal_strstr(module, "libclang_rt.tsan_")))
286 return true;
287 return false;
288}
289
290static SymbolizedStack *SkipTsanInternalFrames(SymbolizedStack *frames) {
291 while (FrameIsInternal(frames) && frames->next)
292 frames = frames->next;
293 return frames;
276static const SymbolizedStack *SkipTsanInternalFrames(SymbolizedStack *frames) {
277 if (const SymbolizedStack *f = SkipInternalFrames(frames))
278 return f;
279 return frames; // Fallback to the top frame.
294280}
295281
296282void PrintReport(const ReportDesc *rep) {
......@@ -364,7 +350,7 @@ void PrintReport(const ReportDesc *rep) {
364350 Printf(" And %d more similar thread leaks.\n\n", rep->count - 1);
365351
366352 if (ReportStack *stack = ChooseSummaryStack(rep)) {
367 if (SymbolizedStack *frame = SkipTsanInternalFrames(stack->frames))
353 if (const SymbolizedStack *frame = SkipTsanInternalFrames(stack->frames))
368354 ReportErrorSummary(rep_typ_str, frame->info);
369355 }
370356
lib/tsan/tsan_report.h+2-1
......@@ -34,7 +34,8 @@ enum ReportType {
3434 ReportTypeMutexBadReadUnlock,
3535 ReportTypeSignalUnsafe,
3636 ReportTypeErrnoInSignal,
37 ReportTypeDeadlock
37 ReportTypeDeadlock,
38 ReportTypeMutexHeldWrongContext
3839};
3940
4041struct ReportStack {
lib/tsan/tsan_rtl.cpp+14-10
......@@ -35,8 +35,10 @@ extern "C" void __tsan_resume() {
3535 __tsan_resumed = 1;
3636}
3737
38#if SANITIZER_APPLE
3839SANITIZER_WEAK_DEFAULT_IMPL
3940void __tsan_test_only_on_fork() {}
41#endif
4042
4143namespace __tsan {
4244
......@@ -46,11 +48,10 @@ int (*on_finalize)(int);
4648#endif
4749
4850#if !SANITIZER_GO && !SANITIZER_APPLE
49__attribute__((tls_model("initial-exec")))
50THREADLOCAL char cur_thread_placeholder[sizeof(ThreadState)] ALIGNED(
51 SANITIZER_CACHE_LINE_SIZE);
51alignas(SANITIZER_CACHE_LINE_SIZE) THREADLOCAL __attribute__((tls_model(
52 "initial-exec"))) char cur_thread_placeholder[sizeof(ThreadState)];
5253#endif
53static char ctx_placeholder[sizeof(Context)] ALIGNED(SANITIZER_CACHE_LINE_SIZE);
54alignas(SANITIZER_CACHE_LINE_SIZE) static char ctx_placeholder[sizeof(Context)];
5455Context *ctx;
5556
5657// Can be overriden by a front-end.
......@@ -446,7 +447,7 @@ static bool InitializeMemoryProfiler() {
446447 ctx->memprof_fd = 2;
447448 } else {
448449 InternalScopedString filename;
449 filename.append("%s.%d", fname, (int)internal_getpid());
450 filename.AppendF("%s.%d", fname, (int)internal_getpid());
450451 ctx->memprof_fd = OpenFile(filename.data(), WrOnly);
451452 if (ctx->memprof_fd == kInvalidFd) {
452453 Printf("ThreadSanitizer: failed to open memory profile file '%s'\n",
......@@ -813,7 +814,7 @@ void ForkBefore(ThreadState* thr, uptr pc) SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
813814 ctx->thread_registry.Lock();
814815 ctx->slot_mtx.Lock();
815816 ScopedErrorReportLock::Lock();
816 AllocatorLock();
817 AllocatorLockBeforeFork();
817818 // Suppress all reports in the pthread_atfork callbacks.
818819 // Reports will deadlock on the report_mtx.
819820 // We could ignore sync operations as well,
......@@ -828,14 +829,17 @@ void ForkBefore(ThreadState* thr, uptr pc) SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
828829 // Disables memory write in OnUserAlloc/Free.
829830 thr->ignore_reads_and_writes++;
830831
832# if SANITIZER_APPLE
831833 __tsan_test_only_on_fork();
834# endif
832835}
833836
834static void ForkAfter(ThreadState* thr) SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
837static void ForkAfter(ThreadState* thr,
838 bool child) SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
835839 thr->suppress_reports--; // Enabled in ForkBefore.
836840 thr->ignore_interceptors--;
837841 thr->ignore_reads_and_writes--;
838 AllocatorUnlock();
842 AllocatorUnlockAfterFork(child);
839843 ScopedErrorReportLock::Unlock();
840844 ctx->slot_mtx.Unlock();
841845 ctx->thread_registry.Unlock();
......@@ -845,10 +849,10 @@ static void ForkAfter(ThreadState* thr) SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
845849 GlobalProcessorUnlock();
846850}
847851
848void ForkParentAfter(ThreadState* thr, uptr pc) { ForkAfter(thr); }
852void ForkParentAfter(ThreadState* thr, uptr pc) { ForkAfter(thr, false); }
849853
850854void ForkChildAfter(ThreadState* thr, uptr pc, bool start_thread) {
851 ForkAfter(thr);
855 ForkAfter(thr, true);
852856 u32 nthread = ctx->thread_registry.OnFork(thr->tid);
853857 VPrintf(1,
854858 "ThreadSanitizer: forked new process with pid %d,"
lib/tsan/tsan_rtl.h+6-6
......@@ -56,8 +56,8 @@ namespace __tsan {
5656
5757#if !SANITIZER_GO
5858struct MapUnmapCallback;
59#if defined(__mips64) || defined(__aarch64__) || defined(__loongarch__) || \
60 defined(__powerpc__)
59# if defined(__mips64) || defined(__aarch64__) || defined(__loongarch__) || \
60 defined(__powerpc__) || SANITIZER_RISCV64
6161
6262struct AP32 {
6363 static const uptr kSpaceBeg = 0;
......@@ -136,7 +136,7 @@ struct TidEpoch {
136136 Epoch epoch;
137137};
138138
139struct TidSlot {
139struct alignas(SANITIZER_CACHE_LINE_SIZE) TidSlot {
140140 Mutex mtx;
141141 Sid sid;
142142 atomic_uint32_t raw_epoch;
......@@ -153,10 +153,10 @@ struct TidSlot {
153153 }
154154
155155 TidSlot();
156} ALIGNED(SANITIZER_CACHE_LINE_SIZE);
156};
157157
158158// This struct is stored in TLS.
159struct ThreadState {
159struct alignas(SANITIZER_CACHE_LINE_SIZE) ThreadState {
160160 FastState fast_state;
161161 int ignore_sync;
162162#if !SANITIZER_GO
......@@ -234,7 +234,7 @@ struct ThreadState {
234234 const ReportDesc *current_report;
235235
236236 explicit ThreadState(Tid tid);
237} ALIGNED(SANITIZER_CACHE_LINE_SIZE);
237};
238238
239239#if !SANITIZER_GO
240240#if SANITIZER_APPLE || SANITIZER_ANDROID
lib/tsan/tsan_rtl_aarch64.S+7
......@@ -2,6 +2,7 @@
22#if defined(__aarch64__)
33
44#include "sanitizer_common/sanitizer_asm.h"
5#include "builtins/assembly.h"
56
67#if !defined(__APPLE__)
78.section .text
......@@ -16,6 +17,7 @@ ASM_HIDDEN(__tsan_setjmp)
1617ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(setjmp))
1718ASM_SYMBOL_INTERCEPTOR(setjmp):
1819 CFI_STARTPROC
20 BTI_C
1921
2022 // Save frame/link register
2123 stp x29, x30, [sp, -32]!
......@@ -66,6 +68,7 @@ ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(setjmp))
6668ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(_setjmp))
6769ASM_SYMBOL_INTERCEPTOR(_setjmp):
6870 CFI_STARTPROC
71 BTI_C
6972
7073 // Save frame/link register
7174 stp x29, x30, [sp, -32]!
......@@ -116,6 +119,7 @@ ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(_setjmp))
116119ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(sigsetjmp))
117120ASM_SYMBOL_INTERCEPTOR(sigsetjmp):
118121 CFI_STARTPROC
122 BTI_C
119123
120124 // Save frame/link register
121125 stp x29, x30, [sp, -32]!
......@@ -168,6 +172,7 @@ ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(sigsetjmp))
168172ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(__sigsetjmp))
169173ASM_SYMBOL_INTERCEPTOR(__sigsetjmp):
170174 CFI_STARTPROC
175 BTI_C
171176
172177 // Save frame/link register
173178 stp x29, x30, [sp, -32]!
......@@ -217,4 +222,6 @@ ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(__sigsetjmp))
217222
218223NO_EXEC_STACK_DIRECTIVE
219224
225GNU_PROPERTY_BTI_PAC
226
220227#endif
lib/tsan/tsan_rtl_access.cpp+14-8
......@@ -672,22 +672,28 @@ void MemoryAccessRangeT(ThreadState* thr, uptr pc, uptr addr, uptr size) {
672672
673673#if SANITIZER_DEBUG
674674 if (!IsAppMem(addr)) {
675 Printf("Access to non app mem %zx\n", addr);
675 Printf("Access to non app mem start: %p\n", (void*)addr);
676676 DCHECK(IsAppMem(addr));
677677 }
678678 if (!IsAppMem(addr + size - 1)) {
679 Printf("Access to non app mem %zx\n", addr + size - 1);
679 Printf("Access to non app mem end: %p\n", (void*)(addr + size - 1));
680680 DCHECK(IsAppMem(addr + size - 1));
681681 }
682682 if (!IsShadowMem(shadow_mem)) {
683 Printf("Bad shadow addr %p (%zx)\n", static_cast<void*>(shadow_mem), addr);
683 Printf("Bad shadow start addr: %p (%p)\n", shadow_mem, (void*)addr);
684684 DCHECK(IsShadowMem(shadow_mem));
685685 }
686 if (!IsShadowMem(shadow_mem + size * kShadowCnt - 1)) {
687 Printf("Bad shadow addr %p (%zx)\n",
688 static_cast<void*>(shadow_mem + size * kShadowCnt - 1),
689 addr + size - 1);
690 DCHECK(IsShadowMem(shadow_mem + size * kShadowCnt - 1));
686
687 RawShadow* shadow_mem_end = reinterpret_cast<RawShadow*>(
688 reinterpret_cast<uptr>(shadow_mem) + size * kShadowMultiplier - 1);
689 if (!IsShadowMem(shadow_mem_end)) {
690 Printf("Bad shadow end addr: %p (%p)\n", shadow_mem_end,
691 (void*)(addr + size - 1));
692 Printf(
693 "Shadow start addr (ok): %p (%p); size: 0x%zx; kShadowMultiplier: "
694 "%zx\n",
695 shadow_mem, (void*)addr, size, kShadowMultiplier);
696 DCHECK(IsShadowMem(shadow_mem_end));
691697 }
692698#endif
693699
lib/tsan/tsan_rtl_loongarch64.S created+196
......@@ -0,0 +1,196 @@
1#include "sanitizer_common/sanitizer_asm.h"
2
3.section .text
4
5ASM_HIDDEN(__tsan_setjmp)
6.comm _ZN14__interception11real_setjmpE,8,8
7.globl ASM_SYMBOL_INTERCEPTOR(setjmp)
8ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(setjmp))
9ASM_SYMBOL_INTERCEPTOR(setjmp):
10 CFI_STARTPROC
11
12 // Save frame pointer and return address register
13 addi.d $sp, $sp, -32
14 st.d $ra, $sp, 24
15 st.d $fp, $sp, 16
16 CFI_DEF_CFA_OFFSET (32)
17 CFI_OFFSET (1, -8)
18 CFI_OFFSET (22, -16)
19
20 // Adjust the SP for previous frame
21 addi.d $fp, $sp, 32
22 CFI_DEF_CFA_REGISTER (22)
23
24 // Save env parameter
25 st.d $a0, $sp, 8
26 CFI_OFFSET (4, -24)
27
28 // Obtain SP, first argument to `void __tsan_setjmp(uptr sp)`
29 addi.d $a0, $fp, 0
30
31 // call tsan interceptor
32 bl ASM_SYMBOL(__tsan_setjmp)
33
34 // Restore env parameter
35 ld.d $a0, $sp, 8
36 CFI_RESTORE (4)
37
38 // Restore frame/link register
39 ld.d $fp, $sp, 16
40 ld.d $ra, $sp, 24
41 addi.d $sp, $sp, 32
42 CFI_RESTORE (22)
43 CFI_RESTORE (1)
44 CFI_DEF_CFA (3, 0)
45
46 // tail jump to libc setjmp
47 la.local $a1, _ZN14__interception11real_setjmpE
48 ld.d $a1, $a1, 0
49 jr $a1
50
51 CFI_ENDPROC
52ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(setjmp))
53
54.comm _ZN14__interception12real__setjmpE,8,8
55.globl ASM_SYMBOL_INTERCEPTOR(_setjmp)
56ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(_setjmp))
57ASM_SYMBOL_INTERCEPTOR(_setjmp):
58 CFI_STARTPROC
59
60 // Save frame pointer and return address register
61 addi.d $sp, $sp, -32
62 st.d $ra, $sp, 24
63 st.d $fp, $sp, 16
64 CFI_DEF_CFA_OFFSET (32)
65 CFI_OFFSET (1, -8)
66 CFI_OFFSET (22, -16)
67
68 // Adjust the SP for previous frame
69 addi.d $fp, $sp, 32
70 CFI_DEF_CFA_REGISTER (22)
71
72 // Save env parameter
73 st.d $a0, $sp, 8
74 CFI_OFFSET (4, -24)
75
76 // Obtain SP, first argument to `void __tsan_setjmp(uptr sp)`
77 addi.d $a0, $fp, 0
78
79 // call tsan interceptor
80 bl ASM_SYMBOL(__tsan_setjmp)
81
82 // Restore env parameter
83 ld.d $a0, $sp, 8
84 CFI_RESTORE (4)
85
86 // Restore frame/link register
87 ld.d $fp, $sp, 16
88 ld.d $ra, $sp, 24
89 addi.d $sp, $sp, 32
90 CFI_RESTORE (22)
91 CFI_RESTORE (1)
92 CFI_DEF_CFA (3, 0)
93
94 // tail jump to libc setjmp
95 la.local $a1, _ZN14__interception12real__setjmpE
96 ld.d $a1, $a1, 0
97 jr $a1
98
99 CFI_ENDPROC
100ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(_setjmp))
101
102.comm _ZN14__interception14real_sigsetjmpE,8,8
103.globl ASM_SYMBOL_INTERCEPTOR(sigsetjmp)
104ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(sigsetjmp))
105ASM_SYMBOL_INTERCEPTOR(sigsetjmp):
106 CFI_STARTPROC
107
108 // Save frame pointer and return address register
109 addi.d $sp, $sp, -32
110 st.d $ra, $sp, 24
111 st.d $fp, $sp, 16
112 CFI_DEF_CFA_OFFSET (32)
113 CFI_OFFSET (1, -8)
114 CFI_OFFSET (22, -16)
115
116 // Adjust the SP for previous frame
117 addi.d $fp, $sp, 32
118 CFI_DEF_CFA_REGISTER (22)
119
120 // Save env parameter
121 st.d $a0, $sp, 8
122 CFI_OFFSET (4, -24)
123
124 // Obtain SP, first argument to `void __tsan_setjmp(uptr sp)`
125 addi.d $a0, $fp, 0
126
127 // call tsan interceptor
128 bl ASM_SYMBOL(__tsan_setjmp)
129
130 // Restore env parameter
131 ld.d $a0, $sp, 8
132 CFI_RESTORE (4)
133
134 // Restore frame/link register
135 ld.d $fp, $sp, 16
136 ld.d $ra, $sp, 24
137 addi.d $sp, $sp, 32
138 CFI_RESTORE (22)
139 CFI_RESTORE (1)
140 CFI_DEF_CFA (3, 0)
141
142 // tail jump to libc setjmp
143 la.local $a1, _ZN14__interception14real_sigsetjmpE
144 ld.d $a1, $a1, 0
145 jr $a1
146
147 CFI_ENDPROC
148ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(sigsetjmp))
149
150.comm _ZN14__interception16real___sigsetjmpE,8,8
151.globl ASM_SYMBOL_INTERCEPTOR(__sigsetjmp)
152ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(__sigsetjmp))
153ASM_SYMBOL_INTERCEPTOR(__sigsetjmp):
154 CFI_STARTPROC
155
156 // Save frame pointer and return address register
157 addi.d $sp, $sp, -32
158 st.d $ra, $sp, 24
159 st.d $fp, $sp, 16
160 CFI_DEF_CFA_OFFSET (32)
161 CFI_OFFSET (1, -8)
162 CFI_OFFSET (22, -16)
163
164 // Adjust the SP for previous frame
165 addi.d $fp, $sp, 32
166 CFI_DEF_CFA_REGISTER (22)
167
168 // Save env parameter
169 st.d $a0, $sp, 8
170 CFI_OFFSET (4, -24)
171
172 // Obtain SP, first argument to `void __tsan_setjmp(uptr sp)`
173 addi.d $a0, $fp, 0
174
175 // call tsan interceptor
176 bl ASM_SYMBOL(__tsan_setjmp)
177
178 // Restore env parameter
179 ld.d $a0, $sp, 8
180 CFI_RESTORE (4)
181
182 // Restore frame/link register
183 ld.d $fp, $sp, 16
184 ld.d $ra, $sp, 24
185 addi.d $sp, $sp, 32
186 CFI_RESTORE (22)
187 CFI_RESTORE (1)
188 CFI_DEF_CFA (3, 0)
189
190 // tail jump to libc setjmp
191 la.local $a1, _ZN14__interception16real___sigsetjmpE
192 ld.d $a1, $a1, 0
193 jr $a1
194
195 CFI_ENDPROC
196ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(__sigsetjmp))
lib/tsan/tsan_rtl_mutex.cpp+1-1
......@@ -446,9 +446,9 @@ void Acquire(ThreadState *thr, uptr pc, uptr addr) {
446446 if (!s)
447447 return;
448448 SlotLocker locker(thr);
449 ReadLock lock(&s->mtx);
449450 if (!s->clock)
450451 return;
451 ReadLock lock(&s->mtx);
452452 thr->clock.Acquire(s->clock);
453453}
454454
lib/tsan/tsan_rtl_riscv64.S created+203
......@@ -0,0 +1,203 @@
1#include "sanitizer_common/sanitizer_asm.h"
2
3.section .text
4
5.comm _ZN14__interception11real_setjmpE,8,8
6.globl ASM_SYMBOL_INTERCEPTOR(setjmp)
7ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(setjmp))
8ASM_SYMBOL_INTERCEPTOR(setjmp):
9 CFI_STARTPROC
10
11 // Save frame pointer and return address register
12 addi sp, sp, -32
13 sd ra, 24(sp)
14 sd s0, 16(sp)
15 CFI_DEF_CFA_OFFSET (32)
16 CFI_OFFSET (1, -8)
17 CFI_OFFSET (8, -16)
18
19 // Adjust the SP for previous frame
20 addi s0, sp, 32
21 CFI_DEF_CFA_REGISTER (8)
22
23 // Save env parameter
24 sd a0, 8(sp)
25 CFI_OFFSET (10, -24)
26
27 // Obtain SP, first argument to `void __tsan_setjmp(uptr sp)`
28 addi a0, s0, 0
29
30 // call tsan interceptor
31 call ASM_SYMBOL(__tsan_setjmp)
32
33 // Restore env parameter
34 ld a0, 8(sp)
35 CFI_RESTORE (10)
36
37 // Restore frame/link register
38 ld s0, 16(sp)
39 ld ra, 24(sp)
40 addi sp, sp, 32
41 CFI_RESTORE (8)
42 CFI_RESTORE (1)
43 CFI_DEF_CFA (2, 0)
44
45 // tail jump to libc setjmp
46 la t1, _ZN14__interception11real_setjmpE
47 ld t1, 0(t1)
48 jr t1
49
50 CFI_ENDPROC
51ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(setjmp))
52
53.comm _ZN14__interception12real__setjmpE,8,8
54.globl ASM_SYMBOL_INTERCEPTOR(_setjmp)
55ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(_setjmp))
56ASM_SYMBOL_INTERCEPTOR(_setjmp):
57 CFI_STARTPROC
58
59 // Save frame pointer and return address register
60 addi sp, sp, -32
61 sd ra, 24(sp)
62 sd s0, 16(sp)
63 CFI_DEF_CFA_OFFSET (32)
64 CFI_OFFSET (1, -8)
65 CFI_OFFSET (8, -16)
66
67 // Adjust the SP for previous frame
68 addi s0, sp, 32
69 CFI_DEF_CFA_REGISTER (8)
70
71 // Save env parameter
72 sd a0, 8(sp)
73 CFI_OFFSET (10, -24)
74
75 // Obtain SP, first argument to `void __tsan_setjmp(uptr sp)`
76 addi a0, s0, 0
77
78 // call tsan interceptor
79 call ASM_SYMBOL(__tsan_setjmp)
80
81 // Restore env parameter
82 ld a0, 8(sp)
83 CFI_RESTORE (10)
84
85 // Restore frame/link register
86 ld s0, 16(sp)
87 ld ra, 24(sp)
88 addi sp, sp, 32
89 CFI_RESTORE (8)
90 CFI_RESTORE (1)
91 CFI_DEF_CFA (2, 0)
92
93 // tail jump to libc setjmp
94 la t1, _ZN14__interception12real__setjmpE
95 ld t1, 0(t1)
96 jr t1
97
98 CFI_ENDPROC
99ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(_setjmp))
100
101.comm _ZN14__interception14real_sigsetjmpE,8,8
102.globl ASM_SYMBOL_INTERCEPTOR(sigsetjmp)
103ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(sigsetjmp))
104ASM_SYMBOL_INTERCEPTOR(sigsetjmp):
105 CFI_STARTPROC
106
107 // Save frame pointer and return address register
108 addi sp, sp, -32
109 sd ra, 24(sp)
110 sd s0, 16(sp)
111 CFI_DEF_CFA_OFFSET (32)
112 CFI_OFFSET (1, -8)
113 CFI_OFFSET (8, -16)
114
115 // Adjust the SP for previous frame
116 addi s0, sp, 32
117 CFI_DEF_CFA_REGISTER (8)
118
119 // Save env parameter
120 sd a0, 8(sp)
121 sd a1, 0(sp)
122 CFI_OFFSET (10, -24)
123 CFI_OFFSET (11, -32)
124
125 // Obtain SP, first argument to `void __tsan_setjmp(uptr sp)`
126 addi a0, s0, 0
127
128 // call tsan interceptor
129 call ASM_SYMBOL(__tsan_setjmp)
130
131 // Restore env parameter
132 ld a0, 8(sp)
133 ld a1, 0(sp)
134 CFI_RESTORE (10)
135 CFI_RESTORE (11)
136
137 // Restore frame/link register
138 ld s0, 16(sp)
139 ld ra, 24(sp)
140 addi sp, sp, 32
141 CFI_RESTORE (8)
142 CFI_RESTORE (1)
143 CFI_DEF_CFA (2, 0)
144
145 // tail jump to libc setjmp
146 la t1, _ZN14__interception14real_sigsetjmpE
147 ld t1, 0(t1)
148 jr t1
149
150 CFI_ENDPROC
151ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(sigsetjmp))
152
153.comm _ZN14__interception16real___sigsetjmpE,8,8
154.globl ASM_SYMBOL_INTERCEPTOR(__sigsetjmp)
155ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(__sigsetjmp))
156ASM_SYMBOL_INTERCEPTOR(__sigsetjmp):
157 CFI_STARTPROC
158
159 // Save frame pointer and return address register
160 addi sp, sp, -32
161 sd ra, 24(sp)
162 sd s0, 16(sp)
163 CFI_DEF_CFA_OFFSET (32)
164 CFI_OFFSET (1, -8)
165 CFI_OFFSET (8, -16)
166
167 // Adjust the SP for previous frame
168 addi s0, sp, 32
169 CFI_DEF_CFA_REGISTER (8)
170
171 // Save env parameter
172 sd a0, 8(sp)
173 sd a1, 0(sp)
174 CFI_OFFSET (10, -24)
175 CFI_OFFSET (11, -32)
176
177 // Obtain SP, first argument to `void __tsan_setjmp(uptr sp)`
178 addi a0, s0, 0
179
180 // call tsan interceptor
181 call ASM_SYMBOL(__tsan_setjmp)
182
183 // Restore env parameter
184 ld a0, 8(sp)
185 ld a1, 0(sp)
186 CFI_RESTORE (10)
187 CFI_RESTORE (11)
188
189 // Restore frame/link register
190 ld s0, 16(sp)
191 ld ra, 24(sp)
192 addi sp, sp, 32
193 CFI_RESTORE (8)
194 CFI_RESTORE (1)
195 CFI_DEF_CFA (2, 0)
196
197 // tail jump to libc setjmp
198 la t1, _ZN14__interception16real___sigsetjmpE
199 ld t1, 0(t1)
200 jr t1
201
202 CFI_ENDPROC
203ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(__sigsetjmp))
lib/tsan/tsan_rtl_s390x.S created+49
......@@ -0,0 +1,49 @@
1#include "sanitizer_common/sanitizer_asm.h"
2
3#define CFA_OFFSET 160
4#define R2_REL_OFFSET 16
5#define R3_REL_OFFSET 24
6#define R14_REL_OFFSET 112
7#define R15_REL_OFFSET 120
8#define FRAME_SIZE 160
9
10.text
11
12ASM_HIDDEN(__tsan_setjmp)
13
14.macro intercept symbol, real
15.comm \real, 8, 8
16.globl ASM_SYMBOL_INTERCEPTOR(\symbol)
17ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(\symbol))
18ASM_SYMBOL_INTERCEPTOR(\symbol):
19 CFI_STARTPROC
20 stmg %r2, %r3, R2_REL_OFFSET(%r15)
21 CFI_REL_OFFSET(%r2, R2_REL_OFFSET)
22 CFI_REL_OFFSET(%r3, R3_REL_OFFSET)
23 stmg %r14, %r15, R14_REL_OFFSET(%r15)
24 CFI_REL_OFFSET(%r14, R14_REL_OFFSET)
25 CFI_REL_OFFSET(%r15, R15_REL_OFFSET)
26 aghi %r15, -FRAME_SIZE
27 CFI_ADJUST_CFA_OFFSET(FRAME_SIZE)
28 la %r2, FRAME_SIZE(%r15)
29 brasl %r14, ASM_SYMBOL(__tsan_setjmp)
30 lmg %r14, %r15, FRAME_SIZE + R14_REL_OFFSET(%r15)
31 CFI_RESTORE(%r14)
32 CFI_RESTORE(%r15)
33 CFI_DEF_CFA_OFFSET(CFA_OFFSET)
34 lmg %r2, %r3, R2_REL_OFFSET(%r15)
35 CFI_RESTORE(%r2)
36 CFI_RESTORE(%r3)
37 larl %r1, \real
38 lg %r1, 0(%r1)
39 br %r1
40 CFI_ENDPROC
41 ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(\symbol))
42.endm
43
44intercept setjmp, _ZN14__interception11real_setjmpE
45intercept _setjmp, _ZN14__interception12real__setjmpE
46intercept sigsetjmp, _ZN14__interception14real_sigsetjmpE
47intercept __sigsetjmp, _ZN14__interception16real___sigsetjmpE
48
49NO_EXEC_STACK_DIRECTIVE
lib/tsan/tsan_rtl_thread.cpp+5-5
......@@ -160,6 +160,10 @@ void ThreadStart(ThreadState *thr, Tid tid, tid_t os_id,
160160 }
161161 Free(thr->tctx->sync);
162162
163#if !SANITIZER_GO
164 thr->is_inited = true;
165#endif
166
163167 uptr stk_addr = 0;
164168 uptr stk_size = 0;
165169 uptr tls_addr = 0;
......@@ -200,15 +204,11 @@ void ThreadStart(ThreadState *thr, Tid tid, tid_t os_id,
200204}
201205
202206void ThreadContext::OnStarted(void *arg) {
203 thr = static_cast<ThreadState *>(arg);
204207 DPrintf("#%d: ThreadStart\n", tid);
205 new (thr) ThreadState(tid);
208 thr = new (arg) ThreadState(tid);
206209 if (common_flags()->detect_deadlocks)
207210 thr->dd_lt = ctx->dd->CreateLogicalThread(tid);
208211 thr->tctx = this;
209#if !SANITIZER_GO
210 thr->is_inited = true;
211#endif
212212}
213213
214214void ThreadFinish(ThreadState *thr) {
lib/tsan/tsan_suppressions.cpp+2-1
......@@ -42,7 +42,7 @@ const char *__tsan_default_suppressions() {
4242
4343namespace __tsan {
4444
45ALIGNED(64) static char suppression_placeholder[sizeof(SuppressionContext)];
45alignas(64) static char suppression_placeholder[sizeof(SuppressionContext)];
4646static SuppressionContext *suppression_ctx = nullptr;
4747static const char *kSuppressionTypes[] = {
4848 kSuppressionRace, kSuppressionRaceTop, kSuppressionMutex,
......@@ -81,6 +81,7 @@ static const char *conv(ReportType typ) {
8181 case ReportTypeMutexBadUnlock:
8282 case ReportTypeMutexBadReadLock:
8383 case ReportTypeMutexBadReadUnlock:
84 case ReportTypeMutexHeldWrongContext:
8485 return kSuppressionMutex;
8586 case ReportTypeSignalUnsafe:
8687 case ReportTypeErrnoInSignal:
lib/tsan/tsan_vector_clock.h+1-1
......@@ -34,7 +34,7 @@ class VectorClock {
3434 VectorClock& operator=(const VectorClock& other);
3535
3636 private:
37 Epoch clk_[kThreadSlotCount] VECTOR_ALIGNED;
37 VECTOR_ALIGNED Epoch clk_[kThreadSlotCount];
3838};
3939
4040ALWAYS_INLINE Epoch VectorClock::Get(Sid sid) const {
src/libtsan.zig+11-5
......@@ -160,10 +160,13 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
160160 }
161161 {
162162 const asm_source = switch (target.cpu.arch) {
163 .aarch64 => "tsan_rtl_aarch64.S",
163 .aarch64, .aarch64_be => "tsan_rtl_aarch64.S",
164 .loongarch64 => "tsan_rtl_loongarch64.S",
165 .mips64, .mips64el => "tsan_rtl_mips64.S",
166 .powerpc64, .powerpc64le => "tsan_rtl_ppc64.S",
167 .riscv64 => "tsan_rtl_riscv64.S",
168 .s390x => "tsan_rtl_s390x.S",
164169 .x86_64 => "tsan_rtl_amd64.S",
165 .mips64 => "tsan_rtl_mips64.S",
166 .powerpc64 => "tsan_rtl_ppc64.S",
167170 else => return error.TSANUnsupportedCPUArchitecture,
168171 };
169172 var cflags = std.ArrayList([]const u8).init(arena);
......@@ -416,7 +419,6 @@ const sanitizer_common_sources = [_][]const u8{
416419 "sanitizer_platform_limits_freebsd.cpp",
417420 "sanitizer_platform_limits_linux.cpp",
418421 "sanitizer_platform_limits_netbsd.cpp",
419 "sanitizer_platform_limits_openbsd.cpp",
420422 "sanitizer_platform_limits_posix.cpp",
421423 "sanitizer_platform_limits_solaris.cpp",
422424 "sanitizer_posix.cpp",
......@@ -429,7 +431,6 @@ const sanitizer_common_sources = [_][]const u8{
429431 "sanitizer_procmaps_solaris.cpp",
430432 "sanitizer_range.cpp",
431433 "sanitizer_solaris.cpp",
432 "sanitizer_stack_store.cpp",
433434 "sanitizer_stoptheworld_fuchsia.cpp",
434435 "sanitizer_stoptheworld_mac.cpp",
435436 "sanitizer_stoptheworld_win.cpp",
......@@ -452,6 +453,7 @@ const sanitizer_nolibc_sources = [_][]const u8{
452453const sanitizer_libcdep_sources = [_][]const u8{
453454 "sanitizer_common_libcdep.cpp",
454455 "sanitizer_allocator_checks.cpp",
456 "sanitizer_dl.cpp",
455457 "sanitizer_linux_libcdep.cpp",
456458 "sanitizer_mac_libcdep.cpp",
457459 "sanitizer_posix_libcdep.cpp",
......@@ -461,6 +463,7 @@ const sanitizer_libcdep_sources = [_][]const u8{
461463
462464const sanitizer_symbolizer_sources = [_][]const u8{
463465 "sanitizer_allocator_report.cpp",
466 "sanitizer_stack_store.cpp",
464467 "sanitizer_stackdepot.cpp",
465468 "sanitizer_stacktrace.cpp",
466469 "sanitizer_stacktrace_libcdep.cpp",
......@@ -471,10 +474,13 @@ const sanitizer_symbolizer_sources = [_][]const u8{
471474 "sanitizer_symbolizer_libcdep.cpp",
472475 "sanitizer_symbolizer_mac.cpp",
473476 "sanitizer_symbolizer_markup.cpp",
477 "sanitizer_symbolizer_markup_fuchsia.cpp",
474478 "sanitizer_symbolizer_posix_libcdep.cpp",
475479 "sanitizer_symbolizer_report.cpp",
480 "sanitizer_symbolizer_report_fuchsia.cpp",
476481 "sanitizer_symbolizer_win.cpp",
477482 "sanitizer_unwind_linux_libcdep.cpp",
483 "sanitizer_unwind_fuchsia.cpp",
478484 "sanitizer_unwind_win.cpp",
479485};
480486