authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-02-05 13:36:56+01:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-04-04 06:08:09+02:00
loge99c11856df5dafb54e92af12c0858d187dc2ad2
tree47602df74eafa2c0d5e58d23ce7b4aef9756832a
parentd67d52abe57b13517013e81562d64bb7c2f77775
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

libtsan: Update to LLVM 20.


83 files changed, 3242 insertions(+), 2047 deletions(-)

lib/tsan/builtins/assembly.h+12
...@@ -290,4 +290,16 @@...@@ -290,4 +290,16 @@
290 CFI_END290 CFI_END
291#endif291#endif
292292
293#ifdef __arm__
294#include "int_endianness.h"
295
296#if _YUGA_BIG_ENDIAN
297#define VMOV_TO_DOUBLE(dst, src0, src1) vmov dst, src1, src0 SEPARATOR
298#define VMOV_FROM_DOUBLE(dst0, dst1, src) vmov dst1, dst0, src SEPARATOR
299#else
300#define VMOV_TO_DOUBLE(dst, src0, src1) vmov dst, src0, src1 SEPARATOR
301#define VMOV_FROM_DOUBLE(dst0, dst1, src) vmov dst0, dst1, src SEPARATOR
302#endif
303#endif
304
293#endif // COMPILERRT_ASSEMBLY_H305#endif // COMPILERRT_ASSEMBLY_H
lib/tsan/interception/interception.h+14-11
...@@ -25,8 +25,19 @@...@@ -25,8 +25,19 @@
2525
26// These typedefs should be used only in the interceptor definitions to replace26// These typedefs should be used only in the interceptor definitions to replace
27// the standard system types (e.g. SSIZE_T instead of ssize_t)27// the standard system types (e.g. SSIZE_T instead of ssize_t)
28typedef __sanitizer::uptr SIZE_T;28// On Windows the system headers (basetsd.h) provide a conflicting definition
29typedef __sanitizer::sptr SSIZE_T;29// of SIZE_T/SSIZE_T that do not match the real size_t/ssize_t for 32-bit
30// systems (using long instead of the expected int). Work around the typedef
31// redefinition by #defining SIZE_T instead of using a typedef.
32// TODO: We should be using __sanitizer::usize (and a new ssize) instead of
33// these new macros as long as we ensure they match the real system definitions.
34#if SANITIZER_WINDOWS
35// Ensure that (S)SIZE_T were already defined as we are about to override them.
36# include <basetsd.h>
37#endif
38
39#define SIZE_T __sanitizer::usize
40#define SSIZE_T __sanitizer::ssize
30typedef __sanitizer::sptr PTRDIFF_T;41typedef __sanitizer::sptr PTRDIFF_T;
31typedef __sanitizer::s64 INTMAX_T;42typedef __sanitizer::s64 INTMAX_T;
32typedef __sanitizer::u64 UINTMAX_T;43typedef __sanitizer::u64 UINTMAX_T;
...@@ -338,16 +349,8 @@ const interpose_substitution substitution_##func_name[] \...@@ -338,16 +349,8 @@ const interpose_substitution substitution_##func_name[] \
338#endif349#endif
339350
340// ISO C++ forbids casting between pointer-to-function and pointer-to-object,351// ISO C++ forbids casting between pointer-to-function and pointer-to-object,
341// so we use casting via an integral type __interception::uptr,352// so we use casts via uintptr_t (the local __sanitizer::uptr equivalent).
342// assuming that system is POSIX-compliant. Using other hacks seem
343// challenging, as we don't even pass function type to
344// INTERCEPT_FUNCTION macro, only its name.
345namespace __interception {353namespace __interception {
346#if defined(_WIN64)
347typedef unsigned long long uptr;
348#else
349typedef unsigned long uptr;
350#endif // _WIN64
351354
352#if defined(__ELF__) && !SANITIZER_FUCHSIA355#if defined(__ELF__) && !SANITIZER_FUCHSIA
353// The use of interceptors makes many sanitizers unusable for static linking.356// The use of interceptors makes many sanitizers unusable for static linking.
lib/tsan/interception/interception_type_test.cpp+19-12
...@@ -12,28 +12,35 @@...@@ -12,28 +12,35 @@
12//===----------------------------------------------------------------------===//12//===----------------------------------------------------------------------===//
1313
14#include "interception.h"14#include "interception.h"
15#include "sanitizer_common/sanitizer_type_traits.h"
1516
16#if SANITIZER_LINUX || SANITIZER_APPLE17#if __has_include(<sys/types.h>)
1718# include <sys/types.h>
18#include <sys/types.h>19#endif
19#include <stddef.h>20#include <stddef.h>
20#include <stdint.h>21#include <stdint.h>
2122
22COMPILER_CHECK(sizeof(::SIZE_T) == sizeof(size_t));23COMPILER_CHECK((__sanitizer::is_same<__sanitizer::uptr, ::uintptr_t>::value));
23COMPILER_CHECK(sizeof(::SSIZE_T) == sizeof(ssize_t));24COMPILER_CHECK((__sanitizer::is_same<__sanitizer::sptr, ::intptr_t>::value));
24COMPILER_CHECK(sizeof(::PTRDIFF_T) == sizeof(ptrdiff_t));25COMPILER_CHECK((__sanitizer::is_same<__sanitizer::usize, ::size_t>::value));
26COMPILER_CHECK((__sanitizer::is_same<::PTRDIFF_T, ::ptrdiff_t>::value));
27COMPILER_CHECK((__sanitizer::is_same<::SIZE_T, ::size_t>::value));
28#if !SANITIZER_WINDOWS
29// No ssize_t on Windows.
30COMPILER_CHECK((__sanitizer::is_same<::SSIZE_T, ::ssize_t>::value));
31#endif
32// TODO: These are not actually the same type on Linux (long vs long long)
25COMPILER_CHECK(sizeof(::INTMAX_T) == sizeof(intmax_t));33COMPILER_CHECK(sizeof(::INTMAX_T) == sizeof(intmax_t));
34COMPILER_CHECK(sizeof(::UINTMAX_T) == sizeof(uintmax_t));
2635
27# if SANITIZER_GLIBC || SANITIZER_ANDROID36#if SANITIZER_GLIBC || SANITIZER_ANDROID
28COMPILER_CHECK(sizeof(::OFF64_T) == sizeof(off64_t));37COMPILER_CHECK(sizeof(::OFF64_T) == sizeof(off64_t));
29# endif38#endif
3039
31// The following are the cases when pread (and friends) is used instead of40// The following are the cases when pread (and friends) is used instead of
32// pread64. In those cases we need OFF_T to match off_t. We don't care about the41// pread64. In those cases we need OFF_T to match off_t. We don't care about the
33// rest (they depend on _FILE_OFFSET_BITS setting when building an application).42// rest (they depend on _FILE_OFFSET_BITS setting when building an application).
34# if SANITIZER_ANDROID || !defined _FILE_OFFSET_BITS || \43#if !SANITIZER_WINDOWS && (SANITIZER_ANDROID || !defined _FILE_OFFSET_BITS || \
35 _FILE_OFFSET_BITS != 6444 _FILE_OFFSET_BITS != 64)
36COMPILER_CHECK(sizeof(::OFF_T) == sizeof(off_t));45COMPILER_CHECK(sizeof(::OFF_T) == sizeof(off_t));
37# endif
38
39#endif46#endif
lib/tsan/interception/interception_win.cpp+364-68
...@@ -27,7 +27,7 @@...@@ -27,7 +27,7 @@
27//27//
28// 1) Detour28// 1) Detour
29//29//
30// The Detour hooking technique is assuming the presence of an header with30// The Detour hooking technique is assuming the presence of a header with
31// padding and an overridable 2-bytes nop instruction (mov edi, edi). The31// padding and an overridable 2-bytes nop instruction (mov edi, edi). The
32// nop instruction can safely be replaced by a 2-bytes jump without any need32// nop instruction can safely be replaced by a 2-bytes jump without any need
33// to save the instruction. A jump to the target is encoded in the function33// to save the instruction. A jump to the target is encoded in the function
...@@ -47,7 +47,7 @@...@@ -47,7 +47,7 @@
47//47//
48// func: jmp <label> --> func: jmp <hook>48// func: jmp <label> --> func: jmp <hook>
49//49//
50// On an 64-bit architecture, a trampoline is inserted.50// On a 64-bit architecture, a trampoline is inserted.
51//51//
52// func: jmp <label> --> func: jmp <tramp>52// func: jmp <label> --> func: jmp <tramp>
53// [...]53// [...]
...@@ -60,7 +60,7 @@...@@ -60,7 +60,7 @@
60//60//
61// 3) HotPatch61// 3) HotPatch
62//62//
63// The HotPatch hooking is assuming the presence of an header with padding63// The HotPatch hooking is assuming the presence of a header with padding
64// and a first instruction with at least 2-bytes.64// and a first instruction with at least 2-bytes.
65//65//
66// The reason to enforce the 2-bytes limitation is to provide the minimal66// The reason to enforce the 2-bytes limitation is to provide the minimal
...@@ -80,7 +80,7 @@...@@ -80,7 +80,7 @@
80// real: <instr>80// real: <instr>
81// jmp <body>81// jmp <body>
82//82//
83// On an 64-bit architecture:83// On a 64-bit architecture:
84//84//
85// head: 6 x nop head: jmp QWORD [addr1]85// head: 6 x nop head: jmp QWORD [addr1]
86// func: <instr> --> func: jmp short <head>86// func: <instr> --> func: jmp short <head>
...@@ -110,7 +110,7 @@...@@ -110,7 +110,7 @@
110// <instr>110// <instr>
111// jmp <body>111// jmp <body>
112//112//
113// On an 64-bit architecture:113// On a 64-bit architecture:
114//114//
115// func: <instr> --> func: jmp QWORD [addr1]115// func: <instr> --> func: jmp QWORD [addr1]
116// <instr>116// <instr>
...@@ -130,6 +130,7 @@...@@ -130,6 +130,7 @@
130#include "sanitizer_common/sanitizer_platform.h"130#include "sanitizer_common/sanitizer_platform.h"
131#define WIN32_LEAN_AND_MEAN131#define WIN32_LEAN_AND_MEAN
132#include <windows.h>132#include <windows.h>
133#include <psapi.h>
133134
134namespace __interception {135namespace __interception {
135136
...@@ -186,8 +187,12 @@ static uptr GetMmapGranularity() {...@@ -186,8 +187,12 @@ static uptr GetMmapGranularity() {
186 return si.dwAllocationGranularity;187 return si.dwAllocationGranularity;
187}188}
188189
190UNUSED static uptr RoundDownTo(uptr size, uptr boundary) {
191 return size & ~(boundary - 1);
192}
193
189UNUSED static uptr RoundUpTo(uptr size, uptr boundary) {194UNUSED static uptr RoundUpTo(uptr size, uptr boundary) {
190 return (size + boundary - 1) & ~(boundary - 1);195 return RoundDownTo(size + boundary - 1, boundary);
191}196}
192197
193// FIXME: internal_str* and internal_mem* functions should be moved from the198// FIXME: internal_str* and internal_mem* functions should be moved from the
...@@ -208,6 +213,18 @@ static char* _strchr(char* str, char c) {...@@ -208,6 +213,18 @@ static char* _strchr(char* str, char c) {
208 return nullptr;213 return nullptr;
209}214}
210215
216static int _strcmp(const char *s1, const char *s2) {
217 while (true) {
218 unsigned c1 = *s1;
219 unsigned c2 = *s2;
220 if (c1 != c2) return (c1 < c2) ? -1 : 1;
221 if (c1 == 0) break;
222 s1++;
223 s2++;
224 }
225 return 0;
226}
227
211static void _memset(void *p, int value, size_t sz) {228static void _memset(void *p, int value, size_t sz) {
212 for (size_t i = 0; i < sz; ++i)229 for (size_t i = 0; i < sz; ++i)
213 ((char*)p)[i] = (char)value;230 ((char*)p)[i] = (char)value;
...@@ -284,8 +301,11 @@ static void WriteJumpInstruction(uptr from, uptr target) {...@@ -284,8 +301,11 @@ static void WriteJumpInstruction(uptr from, uptr target) {
284301
285static void WriteShortJumpInstruction(uptr from, uptr target) {302static void WriteShortJumpInstruction(uptr from, uptr target) {
286 sptr offset = target - from - kShortJumpInstructionLength;303 sptr offset = target - from - kShortJumpInstructionLength;
287 if (offset < -128 || offset > 127)304 if (offset < -128 || offset > 127) {
305 ReportError("interception_win: cannot write short jmp from %p to %p\n",
306 (void *)from, (void *)target);
288 InterceptionFailed();307 InterceptionFailed();
308 }
289 *(u8*)from = 0xEB;309 *(u8*)from = 0xEB;
290 *(u8*)(from + 1) = (u8)offset;310 *(u8*)(from + 1) = (u8)offset;
291}311}
...@@ -339,32 +359,78 @@ struct TrampolineMemoryRegion {...@@ -339,32 +359,78 @@ struct TrampolineMemoryRegion {
339 uptr max_size;359 uptr max_size;
340};360};
341361
342UNUSED static const uptr kTrampolineScanLimitRange = 1ull << 31; // 2 gig362UNUSED static const uptr kTrampolineRangeLimit = 1ull << 31; // 2 gig
343static const int kMaxTrampolineRegion = 1024;363static const int kMaxTrampolineRegion = 1024;
344static TrampolineMemoryRegion TrampolineRegions[kMaxTrampolineRegion];364static TrampolineMemoryRegion TrampolineRegions[kMaxTrampolineRegion];
345365
346static void *AllocateTrampolineRegion(uptr image_address, size_t granularity) {366static void *AllocateTrampolineRegion(uptr min_addr, uptr max_addr,
347#if SANITIZER_WINDOWS64367 uptr func_addr, size_t granularity) {
348 uptr address = image_address;368# if SANITIZER_WINDOWS64
349 uptr scanned = 0;369 // Clamp {min,max}_addr to the accessible address space.
350 while (scanned < kTrampolineScanLimitRange) {370 SYSTEM_INFO system_info;
371 ::GetSystemInfo(&system_info);
372 uptr min_virtual_addr =
373 RoundUpTo((uptr)system_info.lpMinimumApplicationAddress, granularity);
374 uptr max_virtual_addr =
375 RoundDownTo((uptr)system_info.lpMaximumApplicationAddress, granularity);
376 if (min_addr < min_virtual_addr)
377 min_addr = min_virtual_addr;
378 if (max_addr > max_virtual_addr)
379 max_addr = max_virtual_addr;
380
381 // This loop probes the virtual address space to find free memory in the
382 // [min_addr, max_addr] interval. The search starts from func_addr and
383 // proceeds "outwards" towards the interval bounds using two probes, lo_addr
384 // and hi_addr, for addresses lower/higher than func_addr. At each step, it
385 // considers the probe closest to func_addr. If that address is not free, the
386 // probe is advanced (lower or higher depending on the probe) to the next
387 // memory block and the search continues.
388 uptr lo_addr = RoundDownTo(func_addr, granularity);
389 uptr hi_addr = RoundUpTo(func_addr, granularity);
390 while (lo_addr >= min_addr || hi_addr <= max_addr) {
391 // Consider the in-range address closest to func_addr.
392 uptr addr;
393 if (lo_addr < min_addr)
394 addr = hi_addr;
395 else if (hi_addr > max_addr)
396 addr = lo_addr;
397 else
398 addr = (hi_addr - func_addr < func_addr - lo_addr) ? hi_addr : lo_addr;
399
351 MEMORY_BASIC_INFORMATION info;400 MEMORY_BASIC_INFORMATION info;
352 if (!::VirtualQuery((void*)address, &info, sizeof(info)))401 if (!::VirtualQuery((void *)addr, &info, sizeof(info))) {
402 ReportError(
403 "interception_win: VirtualQuery in AllocateTrampolineRegion failed "
404 "for %p\n",
405 (void *)addr);
353 return nullptr;406 return nullptr;
407 }
354408
355 // Check whether a region can be allocated at |address|.409 // Check whether a region can be allocated at |addr|.
356 if (info.State == MEM_FREE && info.RegionSize >= granularity) {410 if (info.State == MEM_FREE && info.RegionSize >= granularity) {
357 void *page = ::VirtualAlloc((void*)RoundUpTo(address, granularity),411 void *page =
358 granularity,412 ::VirtualAlloc((void *)addr, granularity, MEM_RESERVE | MEM_COMMIT,
359 MEM_RESERVE | MEM_COMMIT,413 PAGE_EXECUTE_READWRITE);
360 PAGE_EXECUTE_READWRITE);414 if (page == nullptr)
415 ReportError(
416 "interception_win: VirtualAlloc in AllocateTrampolineRegion failed "
417 "for %p\n",
418 (void *)addr);
361 return page;419 return page;
362 }420 }
363421
364 // Move to the next region.422 if (addr == lo_addr)
365 address = (uptr)info.BaseAddress + info.RegionSize;423 lo_addr =
366 scanned += info.RegionSize;424 RoundDownTo((uptr)info.AllocationBase - granularity, granularity);
425 if (addr == hi_addr)
426 hi_addr =
427 RoundUpTo((uptr)info.BaseAddress + info.RegionSize, granularity);
367 }428 }
429
430 ReportError(
431 "interception_win: AllocateTrampolineRegion failed to find free memory; "
432 "min_addr: %p, max_addr: %p, func_addr: %p, granularity: %zu\n",
433 (void *)min_addr, (void *)max_addr, (void *)func_addr, granularity);
368 return nullptr;434 return nullptr;
369#else435#else
370 return ::VirtualAlloc(nullptr,436 return ::VirtualAlloc(nullptr,
...@@ -385,15 +451,51 @@ void TestOnlyReleaseTrampolineRegions() {...@@ -385,15 +451,51 @@ void TestOnlyReleaseTrampolineRegions() {
385 }451 }
386}452}
387453
388static uptr AllocateMemoryForTrampoline(uptr image_address, size_t size) {454static uptr AllocateMemoryForTrampoline(uptr func_address, size_t size) {
389 // Find a region within 2G with enough space to allocate |size| bytes.455# if SANITIZER_WINDOWS64
456 uptr min_addr = func_address - kTrampolineRangeLimit;
457 uptr max_addr = func_address + kTrampolineRangeLimit - size;
458
459 // Allocate memory within 2GB of the module (DLL or EXE file) so that any
460 // address within the module can be referenced with PC-relative operands.
461 // This allows us to not just jump to the trampoline with a PC-relative
462 // offset, but to relocate any instructions that we copy to the trampoline
463 // which have references to the original module. If we can't find the base
464 // address of the module (e.g. if func_address is in mmap'ed memory), just
465 // stay within 2GB of func_address.
466 HMODULE module;
467 if (::GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
468 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
469 (LPCWSTR)func_address, &module)) {
470 MODULEINFO module_info;
471 if (::GetModuleInformation(::GetCurrentProcess(), module,
472 &module_info, sizeof(module_info))) {
473 min_addr = (uptr)module_info.lpBaseOfDll + module_info.SizeOfImage -
474 kTrampolineRangeLimit;
475 max_addr = (uptr)module_info.lpBaseOfDll + kTrampolineRangeLimit - size;
476 }
477 }
478
479 // Check for overflow.
480 if (min_addr > func_address)
481 min_addr = 0;
482 if (max_addr < func_address)
483 max_addr = ~(uptr)0;
484# else
485 uptr min_addr = 0;
486 uptr max_addr = ~min_addr;
487# endif
488
489 // Find a region within [min_addr,max_addr] with enough space to allocate
490 // |size| bytes.
390 TrampolineMemoryRegion *region = nullptr;491 TrampolineMemoryRegion *region = nullptr;
391 for (size_t bucket = 0; bucket < kMaxTrampolineRegion; ++bucket) {492 for (size_t bucket = 0; bucket < kMaxTrampolineRegion; ++bucket) {
392 TrampolineMemoryRegion* current = &TrampolineRegions[bucket];493 TrampolineMemoryRegion* current = &TrampolineRegions[bucket];
393 if (current->content == 0) {494 if (current->content == 0) {
394 // No valid region found, allocate a new region.495 // No valid region found, allocate a new region.
395 size_t bucket_size = GetMmapGranularity();496 size_t bucket_size = GetMmapGranularity();
396 void *content = AllocateTrampolineRegion(image_address, bucket_size);497 void *content = AllocateTrampolineRegion(min_addr, max_addr, func_address,
498 bucket_size);
397 if (content == nullptr)499 if (content == nullptr)
398 return 0U;500 return 0U;
399501
...@@ -403,13 +505,9 @@ static uptr AllocateMemoryForTrampoline(uptr image_address, size_t size) {...@@ -403,13 +505,9 @@ static uptr AllocateMemoryForTrampoline(uptr image_address, size_t size) {
403 region = current;505 region = current;
404 break;506 break;
405 } else if (current->max_size - current->allocated_size > size) {507 } else if (current->max_size - current->allocated_size > size) {
406#if SANITIZER_WINDOWS64508 uptr next_address = current->content + current->allocated_size;
407 // In 64-bits, the memory space must be allocated within 2G boundary.509 if (next_address < min_addr || next_address > max_addr)
408 uptr next_address = current->content + current->allocated_size;510 continue;
409 if (next_address < image_address ||
410 next_address - image_address >= 0x7FFF0000)
411 continue;
412#endif
413 // The space can be allocated in the current region.511 // The space can be allocated in the current region.
414 region = current;512 region = current;
415 break;513 break;
...@@ -458,6 +556,10 @@ static const u8 kPrologueWithShortJump2[] = {...@@ -458,6 +556,10 @@ static const u8 kPrologueWithShortJump2[] = {
458556
459// Returns 0 on error.557// Returns 0 on error.
460static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {558static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
559 if (rel_offset) {
560 *rel_offset = 0;
561 }
562
461#if SANITIZER_ARM64563#if SANITIZER_ARM64
462 // An ARM64 instruction is 4 bytes long.564 // An ARM64 instruction is 4 bytes long.
463 return 4;565 return 4;
...@@ -497,8 +599,14 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {...@@ -497,8 +599,14 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
497 case 0x6A: // 6A XX = push XX599 case 0x6A: // 6A XX = push XX
498 return 2;600 return 2;
499601
602 // This instruction can be encoded with a 16-bit immediate but that is
603 // incredibly unlikely.
604 case 0x68: // 68 XX XX XX XX : push imm32
605 return 5;
606
500 case 0xb8: // b8 XX XX XX XX : mov eax, XX XX XX XX607 case 0xb8: // b8 XX XX XX XX : mov eax, XX XX XX XX
501 case 0xB9: // b9 XX XX XX XX : mov ecx, XX XX XX XX608 case 0xB9: // b9 XX XX XX XX : mov ecx, XX XX XX XX
609 case 0xBA: // ba XX XX XX XX : mov edx, XX XX XX XX
502 return 5;610 return 5;
503611
504 // Cannot overwrite control-instruction. Return 0 to indicate failure.612 // Cannot overwrite control-instruction. Return 0 to indicate failure.
...@@ -529,19 +637,43 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {...@@ -529,19 +637,43 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
529 case 0xFF8B: // 8B FF : mov edi, edi637 case 0xFF8B: // 8B FF : mov edi, edi
530 case 0xEC8B: // 8B EC : mov ebp, esp638 case 0xEC8B: // 8B EC : mov ebp, esp
531 case 0xc889: // 89 C8 : mov eax, ecx639 case 0xc889: // 89 C8 : mov eax, ecx
640 case 0xD189: // 89 D1 : mov ecx, edx
532 case 0xE589: // 89 E5 : mov ebp, esp641 case 0xE589: // 89 E5 : mov ebp, esp
533 case 0xC18B: // 8B C1 : mov eax, ecx642 case 0xC18B: // 8B C1 : mov eax, ecx
643 case 0xC031: // 31 C0 : xor eax, eax
644 case 0xC931: // 31 C9 : xor ecx, ecx
645 case 0xD231: // 31 D2 : xor edx, edx
534 case 0xC033: // 33 C0 : xor eax, eax646 case 0xC033: // 33 C0 : xor eax, eax
535 case 0xC933: // 33 C9 : xor ecx, ecx647 case 0xC933: // 33 C9 : xor ecx, ecx
536 case 0xD233: // 33 D2 : xor edx, edx648 case 0xD233: // 33 D2 : xor edx, edx
649 case 0xDB84: // 84 DB : test bl,bl
650 case 0xC084: // 84 C0 : test al,al
651 case 0xC984: // 84 C9 : test cl,cl
652 case 0xD284: // 84 D2 : test dl,dl
537 return 2;653 return 2;
538654
655 case 0x3980: // 80 39 XX : cmp BYTE PTR [rcx], XX
656 case 0x4D8B: // 8B 4D XX : mov XX(%ebp), ecx
657 case 0x558B: // 8B 55 XX : mov XX(%ebp), edx
658 case 0x758B: // 8B 75 XX : mov XX(%ebp), esp
659 case 0xE483: // 83 E4 XX : and esp, XX
660 case 0xEC83: // 83 EC XX : sub esp, XX
661 case 0xC1F6: // F6 C1 XX : test cl, XX
662 return 3;
663
664 case 0x89FF: // FF 89 XX XX XX XX : dec dword ptr [ecx + XX XX XX XX]
665 case 0xEC81: // 81 EC XX XX XX XX : sub esp, XX XX XX XX
666 return 6;
667
539 // Cannot overwrite control-instruction. Return 0 to indicate failure.668 // Cannot overwrite control-instruction. Return 0 to indicate failure.
540 case 0x25FF: // FF 25 XX XX XX XX : jmp [XXXXXXXX]669 case 0x25FF: // FF 25 XX YY ZZ WW : jmp dword ptr ds:[WWZZYYXX]
541 return 0;670 return 0;
542 }671 }
543672
544 switch (0x00FFFFFF & *(u32*)address) {673 switch (0x00FFFFFF & *(u32 *)address) {
674 case 0x244C8D: // 8D 4C 24 XX : lea ecx, [esp + XX]
675 case 0x2474FF: // FF 74 24 XX : push qword ptr [rsp + XX]
676 return 4;
545 case 0x24A48D: // 8D A4 24 XX XX XX XX : lea esp, [esp + XX XX XX XX]677 case 0x24A48D: // 8D A4 24 XX XX XX XX : lea esp, [esp + XX XX XX XX]
546 return 7;678 return 7;
547 }679 }
...@@ -556,6 +688,21 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {...@@ -556,6 +688,21 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
556 case 0xA1: // A1 XX XX XX XX XX XX XX XX :688 case 0xA1: // A1 XX XX XX XX XX XX XX XX :
557 // movabs eax, dword ptr ds:[XXXXXXXX]689 // movabs eax, dword ptr ds:[XXXXXXXX]
558 return 9;690 return 9;
691 case 0xF2:
692 switch (*(u32 *)(address + 1)) {
693 case 0x2444110f: // f2 0f 11 44 24 XX movsd QWORD PTR
694 // [rsp + XX], xmm0
695 case 0x244c110f: // f2 0f 11 4c 24 XX movsd QWORD PTR
696 // [rsp + XX], xmm1
697 case 0x2454110f: // f2 0f 11 54 24 XX movsd QWORD PTR
698 // [rsp + XX], xmm2
699 case 0x245c110f: // f2 0f 11 5c 24 XX movsd QWORD PTR
700 // [rsp + XX], xmm3
701 case 0x2464110f: // f2 0f 11 64 24 XX movsd QWORD PTR
702 // [rsp + XX], xmm4
703 return 6;
704 }
705 break;
559706
560 case 0x83:707 case 0x83:
561 const u8 next_byte = *(u8*)(address + 1);708 const u8 next_byte = *(u8*)(address + 1);
...@@ -584,55 +731,155 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {...@@ -584,55 +731,155 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
584 case 0x018a: // mov al, byte ptr [rcx]731 case 0x018a: // mov al, byte ptr [rcx]
585 return 2;732 return 2;
586733
734 case 0x7E80: // 80 7E YY XX cmp BYTE PTR [rsi+YY], XX
735 case 0x7D80: // 80 7D YY XX cmp BYTE PTR [rbp+YY], XX
736 case 0x7A80: // 80 7A YY XX cmp BYTE PTR [rdx+YY], XX
737 case 0x7880: // 80 78 YY XX cmp BYTE PTR [rax+YY], XX
738 case 0x7B80: // 80 7B YY XX cmp BYTE PTR [rbx+YY], XX
739 case 0x7980: // 80 79 YY XX cmp BYTE ptr [rcx+YY], XX
740 return 4;
741
587 case 0x058A: // 8A 05 XX XX XX XX : mov al, byte ptr [XX XX XX XX]742 case 0x058A: // 8A 05 XX XX XX XX : mov al, byte ptr [XX XX XX XX]
588 case 0x058B: // 8B 05 XX XX XX XX : mov eax, dword ptr [XX XX XX XX]743 case 0x058B: // 8B 05 XX XX XX XX : mov eax, dword ptr [XX XX XX XX]
589 if (rel_offset)744 if (rel_offset)
590 *rel_offset = 2;745 *rel_offset = 2;
746 case 0xB841: // 41 B8 XX XX XX XX : mov r8d, XX XX XX XX
591 return 6;747 return 6;
748
749 case 0x7E81: // 81 7E YY XX XX XX XX cmp DWORD PTR [rsi+YY], XX XX XX XX
750 case 0x7D81: // 81 7D YY XX XX XX XX cmp DWORD PTR [rbp+YY], XX XX XX XX
751 case 0x7A81: // 81 7A YY XX XX XX XX cmp DWORD PTR [rdx+YY], XX XX XX XX
752 case 0x7881: // 81 78 YY XX XX XX XX cmp DWORD PTR [rax+YY], XX XX XX XX
753 case 0x7B81: // 81 7B YY XX XX XX XX cmp DWORD PTR [rbx+YY], XX XX XX XX
754 case 0x7981: // 81 79 YY XX XX XX XX cmp dword ptr [rcx+YY], XX XX XX XX
755 return 7;
592 }756 }
593757
594 switch (0x00FFFFFF & *(u32*)address) {758 switch (0x00FFFFFF & *(u32 *)address) {
595 case 0xe58948: // 48 8b c4 : mov rbp, rsp759 case 0x10b70f: // 0f b7 10 : movzx edx, WORD PTR [rax]
596 case 0xc18b48: // 48 8b c1 : mov rax, rcx760 case 0xc00b4d: // 4d 0b c0 : or r8, r8
597 case 0xc48b48: // 48 8b c4 : mov rax, rsp761 case 0xc03345: // 45 33 c0 : xor r8d, r8d
598 case 0xd9f748: // 48 f7 d9 : neg rcx762 case 0xc08548: // 48 85 c0 : test rax, rax
599 case 0xd12b48: // 48 2b d1 : sub rdx, rcx
600 case 0x07c1f6: // f6 c1 07 : test cl, 0x7
601 case 0xc98548: // 48 85 C9 : test rcx, rcx
602 case 0xd28548: // 48 85 d2 : test rdx, rdx
603 case 0xc0854d: // 4d 85 c0 : test r8, r8763 case 0xc0854d: // 4d 85 c0 : test r8, r8
764 case 0xc08b41: // 41 8b c0 : mov eax, r8d
765 case 0xc0ff48: // 48 ff c0 : inc rax
766 case 0xc0ff49: // 49 ff c0 : inc r8
767 case 0xc18b41: // 41 8b c1 : mov eax, r9d
768 case 0xc18b48: // 48 8b c1 : mov rax, rcx
769 case 0xc18b4c: // 4c 8b c1 : mov r8, rcx
770 case 0xc1ff48: // 48 ff c1 : inc rcx
771 case 0xc1ff49: // 49 ff c1 : inc r9
772 case 0xc28b41: // 41 8b c2 : mov eax, r10d
773 case 0x01b60f: // 0f b6 01 : movzx eax, BYTE PTR [rcx]
774 case 0x09b60f: // 0f b6 09 : movzx ecx, BYTE PTR [rcx]
775 case 0x11b60f: // 0f b6 11 : movzx edx, BYTE PTR [rcx]
604 case 0xc2b60f: // 0f b6 c2 : movzx eax, dl776 case 0xc2b60f: // 0f b6 c2 : movzx eax, dl
605 case 0xc03345: // 45 33 c0 : xor r8d, r8d777 case 0xc2ff48: // 48 ff c2 : inc rdx
778 case 0xc2ff49: // 49 ff c2 : inc r10
779 case 0xc38b41: // 41 8b c3 : mov eax, r11d
780 case 0xc3ff48: // 48 ff c3 : inc rbx
781 case 0xc3ff49: // 49 ff c3 : inc r11
782 case 0xc48b41: // 41 8b c4 : mov eax, r12d
783 case 0xc48b48: // 48 8b c4 : mov rax, rsp
784 case 0xc4ff49: // 49 ff c4 : inc r12
785 case 0xc5ff49: // 49 ff c5 : inc r13
786 case 0xc6ff48: // 48 ff c6 : inc rsi
787 case 0xc6ff49: // 49 ff c6 : inc r14
788 case 0xc7ff48: // 48 ff c7 : inc rdi
789 case 0xc7ff49: // 49 ff c7 : inc r15
606 case 0xc93345: // 45 33 c9 : xor r9d, r9d790 case 0xc93345: // 45 33 c9 : xor r9d, r9d
607 case 0xdb3345: // 45 33 DB : xor r11d, r11d791 case 0xc98548: // 48 85 c9 : test rcx, rcx
608 case 0xd98b4c: // 4c 8b d9 : mov r11, rcx792 case 0xc9854d: // 4d 85 c9 : test r9, r9
609 case 0xd28b4c: // 4c 8b d2 : mov r10, rdx793 case 0xc98b4c: // 4c 8b c9 : mov r9, rcx
610 case 0xc98b4c: // 4C 8B C9 : mov r9, rcx794 case 0xd12948: // 48 29 d1 : sub rcx, rdx
611 case 0xc18b4c: // 4C 8B C1 : mov r8, rcx
612 case 0xd2b60f: // 0f b6 d2 : movzx edx, dl
613 case 0xca2b48: // 48 2b ca : sub rcx, rdx795 case 0xca2b48: // 48 2b ca : sub rcx, rdx
614 case 0xca3b48: // 48 3b ca : cmp rcx, rdx796 case 0xca3b48: // 48 3b ca : cmp rcx, rdx
615 case 0x10b70f: // 0f b7 10 : movzx edx, WORD PTR [rax]797 case 0xd12b48: // 48 2b d1 : sub rdx, rcx
616 case 0xc00b4d: // 3d 0b c0 : or r8, r8
617 case 0xc08b41: // 41 8b c0 : mov eax, r8d
618 case 0xd18b48: // 48 8b d1 : mov rdx, rcx798 case 0xd18b48: // 48 8b d1 : mov rdx, rcx
619 case 0xdc8b4c: // 4c 8b dc : mov r11, rsp
620 case 0xd18b4c: // 4c 8b d1 : mov r10, rcx799 case 0xd18b4c: // 4c 8b d1 : mov r10, rcx
621 case 0xE0E483: // 83 E4 E0 : and esp, 0xFFFFFFE0800 case 0xd28548: // 48 85 d2 : test rdx, rdx
801 case 0xd2854d: // 4d 85 d2 : test r10, r10
802 case 0xd28b4c: // 4c 8b d2 : mov r10, rdx
803 case 0xd2b60f: // 0f b6 d2 : movzx edx, dl
804 case 0xd2be0f: // 0f be d2 : movsx edx, dl
805 case 0xd98b4c: // 4c 8b d9 : mov r11, rcx
806 case 0xd9f748: // 48 f7 d9 : neg rcx
807 case 0xc03145: // 45 31 c0 : xor r8d,r8d
808 case 0xc93145: // 45 31 c9 : xor r9d,r9d
809 case 0xdb3345: // 45 33 db : xor r11d, r11d
810 case 0xc08445: // 45 84 c0 : test r8b,r8b
811 case 0xd28445: // 45 84 d2 : test r10b,r10b
812 case 0xdb8548: // 48 85 db : test rbx, rbx
813 case 0xdb854d: // 4d 85 db : test r11, r11
814 case 0xdc8b4c: // 4c 8b dc : mov r11, rsp
815 case 0xe48548: // 48 85 e4 : test rsp, rsp
816 case 0xe4854d: // 4d 85 e4 : test r12, r12
817 case 0xc88948: // 48 89 c8 : mov rax,rcx
818 case 0xcb8948: // 48 89 cb : mov rbx,rcx
819 case 0xd08948: // 48 89 d0 : mov rax,rdx
820 case 0xd18948: // 48 89 d1 : mov rcx,rdx
821 case 0xd38948: // 48 89 d3 : mov rbx,rdx
822 case 0xe58948: // 48 89 e5 : mov rbp, rsp
823 case 0xed8548: // 48 85 ed : test rbp, rbp
824 case 0xc88949: // 49 89 c8 : mov r8, rcx
825 case 0xc98949: // 49 89 c9 : mov r9, rcx
826 case 0xca8949: // 49 89 ca : mov r10,rcx
827 case 0xd08949: // 49 89 d0 : mov r8, rdx
828 case 0xd18949: // 49 89 d1 : mov r9, rdx
829 case 0xd28949: // 49 89 d2 : mov r10, rdx
830 case 0xd38949: // 49 89 d3 : mov r11, rdx
831 case 0xed854d: // 4d 85 ed : test r13, r13
832 case 0xf6854d: // 4d 85 f6 : test r14, r14
833 case 0xff854d: // 4d 85 ff : test r15, r15
622 return 3;834 return 3;
623835
836 case 0x245489: // 89 54 24 XX : mov DWORD PTR[rsp + XX], edx
837 case 0x428d44: // 44 8d 42 XX : lea r8d , [rdx + XX]
838 case 0x588948: // 48 89 58 XX : mov QWORD PTR[rax + XX], rbx
624 case 0xec8348: // 48 83 ec XX : sub rsp, XX839 case 0xec8348: // 48 83 ec XX : sub rsp, XX
625 case 0xf88349: // 49 83 f8 XX : cmp r8, XX840 case 0xf88349: // 49 83 f8 XX : cmp r8, XX
626 case 0x588948: // 48 89 58 XX : mov QWORD PTR[rax + XX], rbx841 case 0x488d49: // 49 8d 48 XX : lea rcx, [...]
842 case 0x048d4c: // 4c 8d 04 XX : lea r8, [...]
843 case 0x148d4e: // 4e 8d 14 XX : lea r10, [...]
844 case 0x398366: // 66 83 39 XX : cmp WORD PTR [rcx], XX
627 return 4;845 return 4;
628846
847 case 0x441F0F: // 0F 1F 44 XX XX : nop DWORD PTR [...]
848 case 0x246483: // 83 64 24 XX YY : and DWORD PTR [rsp+XX], YY
849 return 5;
850
851 case 0x788166: // 66 81 78 XX YY YY cmp WORD PTR [rax+XX], YY YY
852 case 0x798166: // 66 81 79 XX YY YY cmp WORD PTR [rcx+XX], YY YY
853 case 0x7a8166: // 66 81 7a XX YY YY cmp WORD PTR [rdx+XX], YY YY
854 case 0x7b8166: // 66 81 7b XX YY YY cmp WORD PTR [rbx+XX], YY YY
855 case 0x7e8166: // 66 81 7e XX YY YY cmp WORD PTR [rsi+XX], YY YY
856 case 0x7f8166: // 66 81 7f XX YY YY cmp WORD PTR [rdi+XX], YY YY
857 return 6;
858
629 case 0xec8148: // 48 81 EC XX XX XX XX : sub rsp, XXXXXXXX859 case 0xec8148: // 48 81 EC XX XX XX XX : sub rsp, XXXXXXXX
860 case 0xc0c748: // 48 C7 C0 XX XX XX XX : mov rax, XX XX XX XX
630 return 7;861 return 7;
631862
863 // clang-format off
864 case 0x788141: // 41 81 78 XX YY YY YY YY : cmp DWORD PTR [r8+YY], XX XX XX XX
865 case 0x798141: // 41 81 79 XX YY YY YY YY : cmp DWORD PTR [r9+YY], XX XX XX XX
866 case 0x7a8141: // 41 81 7a XX YY YY YY YY : cmp DWORD PTR [r10+YY], XX XX XX XX
867 case 0x7b8141: // 41 81 7b XX YY YY YY YY : cmp DWORD PTR [r11+YY], XX XX XX XX
868 case 0x7d8141: // 41 81 7d XX YY YY YY YY : cmp DWORD PTR [r13+YY], XX XX XX XX
869 case 0x7e8141: // 41 81 7e XX YY YY YY YY : cmp DWORD PTR [r14+YY], XX XX XX XX
870 case 0x7f8141: // 41 81 7f YY XX XX XX XX : cmp DWORD PTR [r15+YY], XX XX XX XX
871 case 0x247c81: // 81 7c 24 YY XX XX XX XX : cmp DWORD PTR [rsp+YY], XX XX XX XX
872 return 8;
873 // clang-format on
874
632 case 0x058b48: // 48 8b 05 XX XX XX XX :875 case 0x058b48: // 48 8b 05 XX XX XX XX :
633 // mov rax, QWORD PTR [rip + XXXXXXXX]876 // mov rax, QWORD PTR [rip + XXXXXXXX]
634 case 0x058d48: // 48 8d 05 XX XX XX XX :877 case 0x058d48: // 48 8d 05 XX XX XX XX :
635 // lea rax, QWORD PTR [rip + XXXXXXXX]878 // lea rax, QWORD PTR [rip + XXXXXXXX]
879 case 0x0d8948: // 48 89 0d XX XX XX XX :
880 // mov QWORD PTR [rip + XXXXXXXX], rcx
881 case 0x158948: // 48 89 15 XX XX XX XX :
882 // mov QWORD PTR [rip + XXXXXXXX], rdx
636 case 0x25ff48: // 48 ff 25 XX XX XX XX :883 case 0x25ff48: // 48 ff 25 XX XX XX XX :
637 // rex.W jmp QWORD PTR [rip + XXXXXXXX]884 // rex.W jmp QWORD PTR [rip + XXXXXXXX]
638 case 0x158D4C: // 4c 8d 15 XX XX XX XX : lea r10, [rip + XX]885 case 0x158D4C: // 4c 8d 15 XX XX XX XX : lea r10, [rip + XX]
...@@ -644,9 +891,19 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {...@@ -644,9 +891,19 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
644 case 0x2444c7: // C7 44 24 XX YY YY YY YY891 case 0x2444c7: // C7 44 24 XX YY YY YY YY
645 // mov dword ptr [rsp + XX], YYYYYYYY892 // mov dword ptr [rsp + XX], YYYYYYYY
646 return 8;893 return 8;
894
895 case 0x7c8141: // 41 81 7c ZZ YY XX XX XX XX
896 // cmp DWORD PTR [reg+reg*n+YY], XX XX XX XX
897 return 9;
647 }898 }
648899
649 switch (*(u32*)(address)) {900 switch (*(u32*)(address)) {
901 case 0x01b60f44: // 44 0f b6 01 : movzx r8d, BYTE PTR [rcx]
902 case 0x09b60f44: // 44 0f b6 09 : movzx r9d, BYTE PTR [rcx]
903 case 0x0ab60f44: // 44 0f b6 0a : movzx r8d, BYTE PTR [rdx]
904 case 0x11b60f44: // 44 0f b6 11 : movzx r10d, BYTE PTR [rcx]
905 case 0x1ab60f44: // 44 0f b6 1a : movzx r11d, BYTE PTR [rdx]
906 return 4;
650 case 0x24448b48: // 48 8b 44 24 XX : mov rax, QWORD ptr [rsp + XX]907 case 0x24448b48: // 48 8b 44 24 XX : mov rax, QWORD ptr [rsp + XX]
651 case 0x246c8948: // 48 89 6C 24 XX : mov QWORD ptr [rsp + XX], rbp908 case 0x246c8948: // 48 89 6C 24 XX : mov QWORD ptr [rsp + XX], rbp
652 case 0x245c8948: // 48 89 5c 24 XX : mov QWORD PTR [rsp + XX], rbx909 case 0x245c8948: // 48 89 5c 24 XX : mov QWORD PTR [rsp + XX], rbx
...@@ -656,9 +913,19 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {...@@ -656,9 +913,19 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
656 case 0x24548948: // 48 89 54 24 XX : mov QWORD PTR [rsp + XX], rdx913 case 0x24548948: // 48 89 54 24 XX : mov QWORD PTR [rsp + XX], rdx
657 case 0x244c894c: // 4c 89 4c 24 XX : mov QWORD PTR [rsp + XX], r9914 case 0x244c894c: // 4c 89 4c 24 XX : mov QWORD PTR [rsp + XX], r9
658 case 0x2444894c: // 4c 89 44 24 XX : mov QWORD PTR [rsp + XX], r8915 case 0x2444894c: // 4c 89 44 24 XX : mov QWORD PTR [rsp + XX], r8
916 case 0x244c8944: // 44 89 4c 24 XX mov DWORD PTR [rsp + XX], r9d
917 case 0x24448944: // 44 89 44 24 XX mov DWORD PTR [rsp + XX], r8d
918 case 0x246c8d48: // 48 8d 6c 24 XX : lea rbp, [rsp + XX]
659 return 5;919 return 5;
660 case 0x24648348: // 48 83 64 24 XX : and QWORD PTR [rsp + XX], YY920 case 0x24648348: // 48 83 64 24 XX YY : and QWORD PTR [rsp + XX], YY
661 return 6;921 return 6;
922 case 0x24A48D48: // 48 8D A4 24 XX XX XX XX : lea rsp, [rsp + XX XX XX XX]
923 return 8;
924 }
925
926 switch (0xFFFFFFFFFFULL & *(u64 *)(address)) {
927 case 0xC07E0F4866: // 66 48 0F 7E C0 : movq rax, xmm0
928 return 5;
662 }929 }
663930
664#else931#else
...@@ -671,11 +938,10 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {...@@ -671,11 +938,10 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
671 case 0x458B: // 8B 45 XX : mov eax, dword ptr [ebp + XX]938 case 0x458B: // 8B 45 XX : mov eax, dword ptr [ebp + XX]
672 case 0x5D8B: // 8B 5D XX : mov ebx, dword ptr [ebp + XX]939 case 0x5D8B: // 8B 5D XX : mov ebx, dword ptr [ebp + XX]
673 case 0x7D8B: // 8B 7D XX : mov edi, dword ptr [ebp + XX]940 case 0x7D8B: // 8B 7D XX : mov edi, dword ptr [ebp + XX]
674 case 0xEC83: // 83 EC XX : sub esp, XX941 case 0x758B: // 8B 75 XX : mov esi, dword ptr [ebp + XX]
675 case 0x75FF: // FF 75 XX : push dword ptr [ebp + XX]942 case 0x75FF: // FF 75 XX : push dword ptr [ebp + XX]
676 return 3;943 return 3;
677 case 0xC1F7: // F7 C1 XX YY ZZ WW : test ecx, WWZZYYXX944 case 0xC1F7: // F7 C1 XX YY ZZ WW : test ecx, WWZZYYXX
678 case 0x25FF: // FF 25 XX YY ZZ WW : jmp dword ptr ds:[WWZZYYXX]
679 return 6;945 return 6;
680 case 0x3D83: // 83 3D XX YY ZZ WW TT : cmp TT, WWZZYYXX946 case 0x3D83: // 83 3D XX YY ZZ WW TT : cmp TT, WWZZYYXX
681 return 7;947 return 7;
...@@ -718,6 +984,10 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {...@@ -718,6 +984,10 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
718 return 0;984 return 0;
719}985}
720986
987size_t TestOnlyGetInstructionSize(uptr address, size_t *rel_offset) {
988 return GetInstructionSize(address, rel_offset);
989}
990
721// Returns 0 on error.991// Returns 0 on error.
722static size_t RoundUpToInstrBoundary(size_t size, uptr address) {992static size_t RoundUpToInstrBoundary(size_t size, uptr address) {
723 size_t cursor = 0;993 size_t cursor = 0;
...@@ -745,8 +1015,14 @@ static bool CopyInstructions(uptr to, uptr from, size_t size) {...@@ -745,8 +1015,14 @@ static bool CopyInstructions(uptr to, uptr from, size_t size) {
745 // this will be untrue if relocated_offset \notin [-2**31, 2**31)1015 // this will be untrue if relocated_offset \notin [-2**31, 2**31)
746 s64 delta = to - from;1016 s64 delta = to - from;
747 s64 relocated_offset = *(s32 *)(to + cursor + rel_offset) - delta;1017 s64 relocated_offset = *(s32 *)(to + cursor + rel_offset) - delta;
748 if (-0x8000'0000ll > relocated_offset || relocated_offset > 0x7FFF'FFFFll)1018 if (-0x8000'0000ll > relocated_offset ||
1019 relocated_offset > 0x7FFF'FFFFll) {
1020 ReportError(
1021 "interception_win: CopyInstructions relocated_offset %lld outside "
1022 "32-bit range\n",
1023 (long long)relocated_offset);
749 return false;1024 return false;
1025 }
750# else1026# else
751 // on 32-bit, the relative offset will always be correct1027 // on 32-bit, the relative offset will always be correct
752 s32 delta = to - from;1028 s32 delta = to - from;
...@@ -969,8 +1245,7 @@ static void **InterestingDLLsAvailable() {...@@ -969,8 +1245,7 @@ static void **InterestingDLLsAvailable() {
969 "libc++.dll", // libc++1245 "libc++.dll", // libc++
970 "libunwind.dll", // libunwind1246 "libunwind.dll", // libunwind
971# endif1247# endif
972 // NTDLL should go last as it exports some functions that we should1248 // NTDLL must go last as it gets special treatment in OverrideFunction.
973 // override in the CRT [presumably only used internally].
974 "ntdll.dll",1249 "ntdll.dll",
975 NULL1250 NULL
976 };1251 };
...@@ -1027,7 +1302,7 @@ uptr InternalGetProcAddress(void *module, const char *func_name) {...@@ -1027,7 +1302,7 @@ uptr InternalGetProcAddress(void *module, const char *func_name) {
10271302
1028 for (DWORD i = 0; i < exports->NumberOfNames; i++) {1303 for (DWORD i = 0; i < exports->NumberOfNames; i++) {
1029 RVAPtr<char> name(module, names[i]);1304 RVAPtr<char> name(module, names[i]);
1030 if (!strcmp(func_name, name)) {1305 if (!_strcmp(func_name, name)) {
1031 DWORD index = ordinals[i];1306 DWORD index = ordinals[i];
1032 RVAPtr<char> func(module, functions[index]);1307 RVAPtr<char> func(module, functions[index]);
10331308
...@@ -1040,19 +1315,27 @@ uptr InternalGetProcAddress(void *module, const char *func_name) {...@@ -1040,19 +1315,27 @@ uptr InternalGetProcAddress(void *module, const char *func_name) {
1040 // exported directory.1315 // exported directory.
1041 char function_name[256];1316 char function_name[256];
1042 size_t funtion_name_length = _strlen(func);1317 size_t funtion_name_length = _strlen(func);
1043 if (funtion_name_length >= sizeof(function_name) - 1)1318 if (funtion_name_length >= sizeof(function_name) - 1) {
1319 ReportError("interception_win: func too long: '%s'\n", (char *)func);
1044 InterceptionFailed();1320 InterceptionFailed();
1321 }
10451322
1046 _memcpy(function_name, func, funtion_name_length);1323 _memcpy(function_name, func, funtion_name_length);
1047 function_name[funtion_name_length] = '\0';1324 function_name[funtion_name_length] = '\0';
1048 char* separator = _strchr(function_name, '.');1325 char* separator = _strchr(function_name, '.');
1049 if (!separator)1326 if (!separator) {
1327 ReportError("interception_win: no separator in '%s'\n",
1328 function_name);
1050 InterceptionFailed();1329 InterceptionFailed();
1330 }
1051 *separator = '\0';1331 *separator = '\0';
10521332
1053 void* redirected_module = GetModuleHandleA(function_name);1333 void* redirected_module = GetModuleHandleA(function_name);
1054 if (!redirected_module)1334 if (!redirected_module) {
1335 ReportError("interception_win: GetModuleHandleA failed for '%s'\n",
1336 function_name);
1055 InterceptionFailed();1337 InterceptionFailed();
1338 }
1056 return InternalGetProcAddress(redirected_module, separator + 1);1339 return InternalGetProcAddress(redirected_module, separator + 1);
1057 }1340 }
10581341
...@@ -1065,9 +1348,22 @@ uptr InternalGetProcAddress(void *module, const char *func_name) {...@@ -1065,9 +1348,22 @@ uptr InternalGetProcAddress(void *module, const char *func_name) {
10651348
1066bool OverrideFunction(1349bool OverrideFunction(
1067 const char *func_name, uptr new_func, uptr *orig_old_func) {1350 const char *func_name, uptr new_func, uptr *orig_old_func) {
1351 static const char *kNtDllIgnore[] = {
1352 "memcmp", "memcpy", "memmove", "memset"
1353 };
1354
1068 bool hooked = false;1355 bool hooked = false;
1069 void **DLLs = InterestingDLLsAvailable();1356 void **DLLs = InterestingDLLsAvailable();
1070 for (size_t i = 0; DLLs[i]; ++i) {1357 for (size_t i = 0; DLLs[i]; ++i) {
1358 if (DLLs[i + 1] == nullptr) {
1359 // This is the last DLL, i.e. NTDLL. It exports some functions that
1360 // we only want to override in the CRT.
1361 for (const char *ignored : kNtDllIgnore) {
1362 if (_strcmp(func_name, ignored) == 0)
1363 return hooked;
1364 }
1365 }
1366
1071 uptr func_addr = InternalGetProcAddress(DLLs[i], func_name);1367 uptr func_addr = InternalGetProcAddress(DLLs[i], func_name);
1072 if (func_addr &&1368 if (func_addr &&
1073 OverrideFunction(func_addr, new_func, orig_old_func)) {1369 OverrideFunction(func_addr, new_func, orig_old_func)) {
...@@ -1121,7 +1417,7 @@ bool OverrideImportedFunction(const char *module_to_patch,...@@ -1121,7 +1417,7 @@ bool OverrideImportedFunction(const char *module_to_patch,
1121 RVAPtr<IMAGE_IMPORT_BY_NAME> import_by_name(1417 RVAPtr<IMAGE_IMPORT_BY_NAME> import_by_name(
1122 module, name_table->u1.ForwarderString);1418 module, name_table->u1.ForwarderString);
1123 const char *funcname = &import_by_name->Name[0];1419 const char *funcname = &import_by_name->Name[0];
1124 if (strcmp(funcname, function_name) == 0)1420 if (_strcmp(funcname, function_name) == 0)
1125 break;1421 break;
1126 }1422 }
1127 }1423 }
...@@ -1144,4 +1440,4 @@ bool OverrideImportedFunction(const char *module_to_patch,...@@ -1144,4 +1440,4 @@ bool OverrideImportedFunction(const char *module_to_patch,
11441440
1145} // namespace __interception1441} // namespace __interception
11461442
1147#endif // SANITIZER_APPLE1443#endif // SANITIZER_WINDOWS
lib/tsan/interception/interception_win.h+3
...@@ -63,6 +63,9 @@ bool OverrideFunctionWithTrampoline(...@@ -63,6 +63,9 @@ bool OverrideFunctionWithTrampoline(
63// Exposed for unittests63// Exposed for unittests
64void TestOnlyReleaseTrampolineRegions();64void TestOnlyReleaseTrampolineRegions();
6565
66// Exposed for unittests
67SIZE_T TestOnlyGetInstructionSize(uptr address, SIZE_T *rel_offset);
68
66} // namespace __interception69} // namespace __interception
6770
68#if defined(INTERCEPTION_DYNAMIC_CRT)71#if defined(INTERCEPTION_DYNAMIC_CRT)
lib/tsan/sanitizer_common/sanitizer_allocator.cpp+3-2
...@@ -59,7 +59,7 @@ static void *RawInternalAlloc(uptr size, InternalAllocatorCache *cache,...@@ -59,7 +59,7 @@ static void *RawInternalAlloc(uptr size, InternalAllocatorCache *cache,
5959
60static void *RawInternalRealloc(void *ptr, uptr size,60static void *RawInternalRealloc(void *ptr, uptr size,
61 InternalAllocatorCache *cache) {61 InternalAllocatorCache *cache) {
62 uptr alignment = 8;62 constexpr usize alignment = Max<usize>(8, sizeof(void *));
63 if (cache == 0) {63 if (cache == 0) {
64 SpinMutexLock l(&internal_allocator_cache_mu);64 SpinMutexLock l(&internal_allocator_cache_mu);
65 return internal_allocator()->Reallocate(&internal_allocator_cache, ptr,65 return internal_allocator()->Reallocate(&internal_allocator_cache, ptr,
...@@ -137,7 +137,8 @@ void InternalAllocatorUnlock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {...@@ -137,7 +137,8 @@ void InternalAllocatorUnlock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
137}137}
138138
139// LowLevelAllocator139// LowLevelAllocator
140constexpr uptr kLowLevelAllocatorDefaultAlignment = 8;140constexpr usize kLowLevelAllocatorDefaultAlignment =
141 Max<usize>(8, sizeof(void *));
141constexpr uptr kMinNumPagesRounded = 16;142constexpr uptr kMinNumPagesRounded = 16;
142constexpr uptr kMinRoundedSize = 65536;143constexpr uptr kMinRoundedSize = 65536;
143static uptr low_level_alloc_min_alignment = kLowLevelAllocatorDefaultAlignment;144static uptr low_level_alloc_min_alignment = kLowLevelAllocatorDefaultAlignment;
lib/tsan/sanitizer_common/sanitizer_allocator_dlsym.h+18-9
...@@ -15,6 +15,8 @@...@@ -15,6 +15,8 @@
15#define SANITIZER_ALLOCATOR_DLSYM_H15#define SANITIZER_ALLOCATOR_DLSYM_H
1616
17#include "sanitizer_allocator_internal.h"17#include "sanitizer_allocator_internal.h"
18#include "sanitizer_common/sanitizer_allocator_checks.h"
19#include "sanitizer_common/sanitizer_internal_defs.h"
1820
19namespace __sanitizer {21namespace __sanitizer {
2022
...@@ -31,24 +33,22 @@ struct DlSymAllocator {...@@ -31,24 +33,22 @@ struct DlSymAllocator {
31 UNLIKELY(internal_allocator()->FromPrimary(ptr));33 UNLIKELY(internal_allocator()->FromPrimary(ptr));
32 }34 }
3335
34 static void *Allocate(uptr size_in_bytes) {36 static void *Allocate(uptr size_in_bytes, uptr align = kWordSize) {
35 void *ptr = InternalAlloc(size_in_bytes, nullptr, kWordSize);37 void *ptr = InternalAlloc(size_in_bytes, nullptr, align);
36 CHECK(internal_allocator()->FromPrimary(ptr));38 CHECK(internal_allocator()->FromPrimary(ptr));
37 Details::OnAllocate(ptr,39 Details::OnAllocate(ptr, GetSize(ptr));
38 internal_allocator()->GetActuallyAllocatedSize(ptr));
39 return ptr;40 return ptr;
40 }41 }
4142
42 static void *Callocate(SIZE_T nmemb, SIZE_T size) {43 static void *Callocate(usize nmemb, usize size) {
43 void *ptr = InternalCalloc(nmemb, size);44 void *ptr = InternalCalloc(nmemb, size);
44 CHECK(internal_allocator()->FromPrimary(ptr));45 CHECK(internal_allocator()->FromPrimary(ptr));
45 Details::OnAllocate(ptr,46 Details::OnAllocate(ptr, GetSize(ptr));
46 internal_allocator()->GetActuallyAllocatedSize(ptr));
47 return ptr;47 return ptr;
48 }48 }
4949
50 static void Free(void *ptr) {50 static void Free(void *ptr) {
51 uptr size = internal_allocator()->GetActuallyAllocatedSize(ptr);51 uptr size = GetSize(ptr);
52 Details::OnFree(ptr, size);52 Details::OnFree(ptr, size);
53 InternalFree(ptr);53 InternalFree(ptr);
54 }54 }
...@@ -61,7 +61,7 @@ struct DlSymAllocator {...@@ -61,7 +61,7 @@ struct DlSymAllocator {
61 Free(ptr);61 Free(ptr);
62 return nullptr;62 return nullptr;
63 }63 }
64 uptr size = internal_allocator()->GetActuallyAllocatedSize(ptr);64 uptr size = GetSize(ptr);
65 uptr memcpy_size = Min(new_size, size);65 uptr memcpy_size = Min(new_size, size);
66 void *new_ptr = Allocate(new_size);66 void *new_ptr = Allocate(new_size);
67 if (new_ptr)67 if (new_ptr)
...@@ -70,6 +70,15 @@ struct DlSymAllocator {...@@ -70,6 +70,15 @@ struct DlSymAllocator {
70 return new_ptr;70 return new_ptr;
71 }71 }
7272
73 static void *ReallocArray(void *ptr, uptr count, uptr size) {
74 CHECK(!CheckForCallocOverflow(count, size));
75 return Realloc(ptr, count * size);
76 }
77
78 static uptr GetSize(void *ptr) {
79 return internal_allocator()->GetActuallyAllocatedSize(ptr);
80 }
81
73 static void OnAllocate(const void *ptr, uptr size) {}82 static void OnAllocate(const void *ptr, uptr size) {}
74 static void OnFree(const void *ptr, uptr size) {}83 static void OnFree(const void *ptr, uptr size) {}
75};84};
lib/tsan/sanitizer_common/sanitizer_allocator_primary64.h+7-5
...@@ -185,9 +185,10 @@ class SizeClassAllocator64 {...@@ -185,9 +185,10 @@ class SizeClassAllocator64 {
185 // recoverable.185 // recoverable.
186 if (UNLIKELY(!EnsureFreeArraySpace(region, region_beg,186 if (UNLIKELY(!EnsureFreeArraySpace(region, region_beg,
187 new_num_freed_chunks))) {187 new_num_freed_chunks))) {
188 Report("FATAL: Internal error: %s's allocator exhausted the free list "188 Report(
189 "space for size class %zd (%zd bytes).\n", SanitizerToolName,189 "FATAL: Internal error: %s's allocator exhausted the free list "
190 class_id, ClassIdToSize(class_id));190 "space for size class %zu (%zu bytes).\n",
191 SanitizerToolName, class_id, ClassIdToSize(class_id));
191 Die();192 Die();
192 }193 }
193 for (uptr i = 0; i < n_chunks; i++)194 for (uptr i = 0; i < n_chunks; i++)
...@@ -763,8 +764,9 @@ class SizeClassAllocator64 {...@@ -763,8 +764,9 @@ class SizeClassAllocator64 {
763 if (!region->exhausted) {764 if (!region->exhausted) {
764 region->exhausted = true;765 region->exhausted = true;
765 Printf("%s: Out of memory. ", SanitizerToolName);766 Printf("%s: Out of memory. ", SanitizerToolName);
766 Printf("The process has exhausted %zuMB for size class %zu.\n",767 Printf(
767 kRegionSize >> 20, ClassIdToSize(class_id));768 "The process has exhausted %zu MB for size class %zu (%zu bytes).\n",
769 kRegionSize >> 20, class_id, ClassIdToSize(class_id));
768 }770 }
769 return true;771 return true;
770 }772 }
lib/tsan/sanitizer_common/sanitizer_common.h+18-9
...@@ -83,8 +83,8 @@ int TgKill(pid_t pid, tid_t tid, int sig);...@@ -83,8 +83,8 @@ int TgKill(pid_t pid, tid_t tid, int sig);
83uptr GetThreadSelf();83uptr GetThreadSelf();
84void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,84void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
85 uptr *stack_bottom);85 uptr *stack_bottom);
86void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,86void GetThreadStackAndTls(bool main, uptr *stk_begin, uptr *stk_end,
87 uptr *tls_addr, uptr *tls_size);87 uptr *tls_begin, uptr *tls_end);
8888
89// Memory management89// Memory management
90void *MmapOrDie(uptr size, const char *mem_type, bool raw_report = false);90void *MmapOrDie(uptr size, const char *mem_type, bool raw_report = false);
...@@ -239,13 +239,15 @@ void RemoveANSIEscapeSequencesFromString(char *buffer);...@@ -239,13 +239,15 @@ void RemoveANSIEscapeSequencesFromString(char *buffer);
239void Printf(const char *format, ...) FORMAT(1, 2);239void Printf(const char *format, ...) FORMAT(1, 2);
240void Report(const char *format, ...) FORMAT(1, 2);240void Report(const char *format, ...) FORMAT(1, 2);
241void SetPrintfAndReportCallback(void (*callback)(const char *));241void SetPrintfAndReportCallback(void (*callback)(const char *));
242#define VReport(level, ...) \242#define VReport(level, ...) \
243 do { \243 do { \
244 if ((uptr)Verbosity() >= (level)) Report(__VA_ARGS__); \244 if (UNLIKELY((uptr)Verbosity() >= (level))) \
245 Report(__VA_ARGS__); \
245 } while (0)246 } while (0)
246#define VPrintf(level, ...) \247#define VPrintf(level, ...) \
247 do { \248 do { \
248 if ((uptr)Verbosity() >= (level)) Printf(__VA_ARGS__); \249 if (UNLIKELY((uptr)Verbosity() >= (level))) \
250 Printf(__VA_ARGS__); \
249 } while (0)251 } while (0)
250252
251// Lock sanitizer error reporting and protects against nested errors.253// Lock sanitizer error reporting and protects against nested errors.
...@@ -266,7 +268,15 @@ class ScopedErrorReportLock {...@@ -266,7 +268,15 @@ class ScopedErrorReportLock {
266extern uptr stoptheworld_tracer_pid;268extern uptr stoptheworld_tracer_pid;
267extern uptr stoptheworld_tracer_ppid;269extern uptr stoptheworld_tracer_ppid;
268270
271// Returns true if the entire range can be read.
269bool IsAccessibleMemoryRange(uptr beg, uptr size);272bool IsAccessibleMemoryRange(uptr beg, uptr size);
273// Attempts to copy `n` bytes from memory range starting at `src` to `dest`.
274// Returns true if the entire range can be read. Returns `false` if any part of
275// the source range cannot be read, in which case the contents of `dest` are
276// undefined.
277bool TryMemCpy(void *dest, const void *src, uptr n);
278// Copies accessible memory, and zero fill inaccessible.
279void MemCpyAccessible(void *dest, const void *src, uptr n);
270280
271// Error report formatting.281// Error report formatting.
272const char *StripPathPrefix(const char *filepath,282const char *StripPathPrefix(const char *filepath,
...@@ -917,7 +927,6 @@ typedef void (*RangeIteratorCallback)(uptr begin, uptr end, void *arg);...@@ -917,7 +927,6 @@ typedef void (*RangeIteratorCallback)(uptr begin, uptr end, void *arg);
917927
918enum AndroidApiLevel {928enum AndroidApiLevel {
919 ANDROID_NOT_ANDROID = 0,929 ANDROID_NOT_ANDROID = 0,
920 ANDROID_KITKAT = 19,
921 ANDROID_LOLLIPOP_MR1 = 22,930 ANDROID_LOLLIPOP_MR1 = 22,
922 ANDROID_POST_LOLLIPOP = 23931 ANDROID_POST_LOLLIPOP = 23
923};932};
lib/tsan/sanitizer_common/sanitizer_common_interceptors.inc+189-221
...@@ -41,6 +41,7 @@...@@ -41,6 +41,7 @@
41#include "sanitizer_errno.h"41#include "sanitizer_errno.h"
42#include "sanitizer_placement_new.h"42#include "sanitizer_placement_new.h"
43#include "sanitizer_platform_interceptors.h"43#include "sanitizer_platform_interceptors.h"
44#include "sanitizer_platform_limits_posix.h"
44#include "sanitizer_symbolizer.h"45#include "sanitizer_symbolizer.h"
45#include "sanitizer_tls_get_addr.h"46#include "sanitizer_tls_get_addr.h"
4647
...@@ -127,6 +128,39 @@ extern const short *_toupper_tab_;...@@ -127,6 +128,39 @@ extern const short *_toupper_tab_;
127extern const short *_tolower_tab_;128extern const short *_tolower_tab_;
128#endif129#endif
129130
131#if SANITIZER_LINUX && SANITIZER_SPARC32
132// On 32-bit Linux/sparc64, double and long double are identical and glibc
133// uses a __nldbl_ (no long double) prefix for various stdio functions.
134# define __isoc23_fscanf __nldbl___isoc23_fscanf
135# define __isoc23_scanf __nldbl___isoc23_scanf
136# define __isoc23_sscanf __nldbl___isoc23_sscanf
137# define __isoc23_vfscanf __nldbl___isoc23_vfscanf
138# define __isoc23_vscanf __nldbl___isoc23_vscanf
139# define __isoc23_vsscanf __nldbl___isoc23_vsscanf
140# define __isoc99_fscanf __nldbl___isoc99_fscanf
141# define __isoc99_scanf __nldbl___isoc99_scanf
142# define __isoc99_sscanf __nldbl___isoc99_sscanf
143# define __isoc99_vfscanf __nldbl___isoc99_vfscanf
144# define __isoc99_vscanf __nldbl___isoc99_vscanf
145# define __isoc99_vsscanf __nldbl___isoc99_vsscanf
146# define asprintf __nldbl_asprintf
147# define fprintf __nldbl_fprintf
148# define fscanf __nldbl_fscanf
149# define printf __nldbl_printf
150# define scanf __nldbl_scanf
151# define snprintf __nldbl_snprintf
152# define sprintf __nldbl_sprintf
153# define sscanf __nldbl_sscanf
154# define vasprintf __nldbl_vasprintf
155# define vfprintf __nldbl_vfprintf
156# define vfscanf __nldbl_vfscanf
157# define vprintf __nldbl_vprintf
158# define vscanf __nldbl_vscanf
159# define vsnprintf __nldbl_vsnprintf
160# define vsprintf __nldbl_vsprintf
161# define vsscanf __nldbl_vsscanf
162#endif
163
130#if SANITIZER_MUSL && \164#if SANITIZER_MUSL && \
131 (defined(__i386__) || defined(__arm__) || SANITIZER_MIPS32 || SANITIZER_PPC32)165 (defined(__i386__) || defined(__arm__) || SANITIZER_MIPS32 || SANITIZER_PPC32)
132// musl 1.2.0 on existing 32-bit architectures uses new symbol names for the166// musl 1.2.0 on existing 32-bit architectures uses new symbol names for the
...@@ -313,7 +347,7 @@ extern const short *_tolower_tab_;...@@ -313,7 +347,7 @@ extern const short *_tolower_tab_;
313 uptr copy_length = internal_strnlen(s, size); \347 uptr copy_length = internal_strnlen(s, size); \
314 char *new_mem = (char *)WRAP(malloc)(copy_length + 1); \348 char *new_mem = (char *)WRAP(malloc)(copy_length + 1); \
315 if (common_flags()->intercept_strndup) { \349 if (common_flags()->intercept_strndup) { \
316 COMMON_INTERCEPTOR_READ_STRING(ctx, s, Min(size, copy_length + 1)); \350 COMMON_INTERCEPTOR_READ_STRING(ctx, s, Min<uptr>(size, copy_length + 1)); \
317 } \351 } \
318 if (new_mem) { \352 if (new_mem) { \
319 COMMON_INTERCEPTOR_COPY_STRING(ctx, new_mem, s, copy_length); \353 COMMON_INTERCEPTOR_COPY_STRING(ctx, new_mem, s, copy_length); \
...@@ -411,7 +445,7 @@ INTERCEPTOR(SIZE_T, strnlen, const char *s, SIZE_T maxlen) {...@@ -411,7 +445,7 @@ INTERCEPTOR(SIZE_T, strnlen, const char *s, SIZE_T maxlen) {
411#endif445#endif
412446
413#if SANITIZER_INTERCEPT_STRNDUP447#if SANITIZER_INTERCEPT_STRNDUP
414INTERCEPTOR(char*, strndup, const char *s, uptr size) {448INTERCEPTOR(char*, strndup, const char *s, usize size) {
415 void *ctx;449 void *ctx;
416 COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size);450 COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size);
417}451}
...@@ -421,7 +455,7 @@ INTERCEPTOR(char*, strndup, const char *s, uptr size) {...@@ -421,7 +455,7 @@ INTERCEPTOR(char*, strndup, const char *s, uptr size) {
421#endif // SANITIZER_INTERCEPT_STRNDUP455#endif // SANITIZER_INTERCEPT_STRNDUP
422456
423#if SANITIZER_INTERCEPT___STRNDUP457#if SANITIZER_INTERCEPT___STRNDUP
424INTERCEPTOR(char*, __strndup, const char *s, uptr size) {458INTERCEPTOR(char*, __strndup, const char *s, usize size) {
425 void *ctx;459 void *ctx;
426 COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size);460 COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size);
427}461}
...@@ -477,23 +511,23 @@ INTERCEPTOR(int, strcmp, const char *s1, const char *s2) {...@@ -477,23 +511,23 @@ INTERCEPTOR(int, strcmp, const char *s1, const char *s2) {
477}511}
478512
479DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncmp, uptr called_pc,513DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncmp, uptr called_pc,
480 const char *s1, const char *s2, uptr n,514 const char *s1, const char *s2, usize n,
481 int result)515 int result)
482516
483INTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr size) {517INTERCEPTOR(int, strncmp, const char *s1, const char *s2, usize size) {
484 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)518 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
485 return internal_strncmp(s1, s2, size);519 return internal_strncmp(s1, s2, size);
486 void *ctx;520 void *ctx;
487 COMMON_INTERCEPTOR_ENTER(ctx, strncmp, s1, s2, size);521 COMMON_INTERCEPTOR_ENTER(ctx, strncmp, s1, s2, size);
488 unsigned char c1 = 0, c2 = 0;522 unsigned char c1 = 0, c2 = 0;
489 uptr i;523 usize i;
490 for (i = 0; i < size; i++) {524 for (i = 0; i < size; i++) {
491 c1 = (unsigned char)s1[i];525 c1 = (unsigned char)s1[i];
492 c2 = (unsigned char)s2[i];526 c2 = (unsigned char)s2[i];
493 if (c1 != c2 || c1 == '\0') break;527 if (c1 != c2 || c1 == '\0') break;
494 }528 }
495 uptr i1 = i;529 usize i1 = i;
496 uptr i2 = i;530 usize i2 = i;
497 if (common_flags()->strict_string_checks) {531 if (common_flags()->strict_string_checks) {
498 for (; i1 < size && s1[i1]; i1++) {}532 for (; i1 < size && s1[i1]; i1++) {}
499 for (; i2 < size && s2[i2]; i2++) {}533 for (; i2 < size && s2[i2]; i2++) {}
...@@ -542,21 +576,21 @@ INTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) {...@@ -542,21 +576,21 @@ INTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) {
542}576}
543577
544DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncasecmp, uptr called_pc,578DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncasecmp, uptr called_pc,
545 const char *s1, const char *s2, uptr size,579 const char *s1, const char *s2, usize size,
546 int result)580 int result)
547581
548INTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, SIZE_T size) {582INTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, SIZE_T size) {
549 void *ctx;583 void *ctx;
550 COMMON_INTERCEPTOR_ENTER(ctx, strncasecmp, s1, s2, size);584 COMMON_INTERCEPTOR_ENTER(ctx, strncasecmp, s1, s2, size);
551 unsigned char c1 = 0, c2 = 0;585 unsigned char c1 = 0, c2 = 0;
552 uptr i;586 usize i;
553 for (i = 0; i < size; i++) {587 for (i = 0; i < size; i++) {
554 c1 = (unsigned char)s1[i];588 c1 = (unsigned char)s1[i];
555 c2 = (unsigned char)s2[i];589 c2 = (unsigned char)s2[i];
556 if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;590 if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
557 }591 }
558 uptr i1 = i;592 usize i1 = i;
559 uptr i2 = i;593 usize i2 = i;
560 if (common_flags()->strict_string_checks) {594 if (common_flags()->strict_string_checks) {
561 for (; i1 < size && s1[i1]; i1++) {}595 for (; i1 < size && s1[i1]; i1++) {}
562 for (; i2 < size && s2[i2]; i2++) {}596 for (; i2 < size && s2[i2]; i2++) {}
...@@ -799,13 +833,13 @@ INTERCEPTOR(char *, strpbrk, const char *s1, const char *s2) {...@@ -799,13 +833,13 @@ INTERCEPTOR(char *, strpbrk, const char *s1, const char *s2) {
799833
800#if SANITIZER_INTERCEPT_MEMCMP834#if SANITIZER_INTERCEPT_MEMCMP
801DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, uptr called_pc,835DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, uptr called_pc,
802 const void *s1, const void *s2, uptr n,836 const void *s1, const void *s2, usize n,
803 int result)837 int result)
804838
805// Common code for `memcmp` and `bcmp`.839// Common code for `memcmp` and `bcmp`.
806int MemcmpInterceptorCommon(void *ctx,840int MemcmpInterceptorCommon(void *ctx,
807 int (*real_fn)(const void *, const void *, uptr),841 int (*real_fn)(const void *, const void *, usize),
808 const void *a1, const void *a2, uptr size) {842 const void *a1, const void *a2, usize size) {
809 if (common_flags()->intercept_memcmp) {843 if (common_flags()->intercept_memcmp) {
810 if (common_flags()->strict_memcmp) {844 if (common_flags()->strict_memcmp) {
811 // Check the entire regions even if the first bytes of the buffers are845 // Check the entire regions even if the first bytes of the buffers are
...@@ -817,7 +851,7 @@ int MemcmpInterceptorCommon(void *ctx,...@@ -817,7 +851,7 @@ int MemcmpInterceptorCommon(void *ctx,
817 unsigned char c1 = 0, c2 = 0;851 unsigned char c1 = 0, c2 = 0;
818 const unsigned char *s1 = (const unsigned char*)a1;852 const unsigned char *s1 = (const unsigned char*)a1;
819 const unsigned char *s2 = (const unsigned char*)a2;853 const unsigned char *s2 = (const unsigned char*)a2;
820 uptr i;854 usize i;
821 for (i = 0; i < size; i++) {855 for (i = 0; i < size; i++) {
822 c1 = s1[i];856 c1 = s1[i];
823 c2 = s2[i];857 c2 = s2[i];
...@@ -837,7 +871,7 @@ int MemcmpInterceptorCommon(void *ctx,...@@ -837,7 +871,7 @@ int MemcmpInterceptorCommon(void *ctx,
837 return result;871 return result;
838}872}
839873
840INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {874INTERCEPTOR(int, memcmp, const void *a1, const void *a2, usize size) {
841 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)875 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
842 return internal_memcmp(a1, a2, size);876 return internal_memcmp(a1, a2, size);
843 void *ctx;877 void *ctx;
...@@ -851,7 +885,7 @@ INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {...@@ -851,7 +885,7 @@ INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
851#endif885#endif
852886
853#if SANITIZER_INTERCEPT_BCMP887#if SANITIZER_INTERCEPT_BCMP
854INTERCEPTOR(int, bcmp, const void *a1, const void *a2, uptr size) {888INTERCEPTOR(int, bcmp, const void *a1, const void *a2, usize size) {
855 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)889 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
856 return internal_memcmp(a1, a2, size);890 return internal_memcmp(a1, a2, size);
857 void *ctx;891 void *ctx;
...@@ -1104,7 +1138,7 @@ INTERCEPTOR(SSIZE_T, write, int fd, void *ptr, SIZE_T count) {...@@ -1104,7 +1138,7 @@ INTERCEPTOR(SSIZE_T, write, int fd, void *ptr, SIZE_T count) {
1104#endif1138#endif
11051139
1106#if SANITIZER_INTERCEPT_FWRITE1140#if SANITIZER_INTERCEPT_FWRITE
1107INTERCEPTOR(SIZE_T, fwrite, const void *p, uptr size, uptr nmemb, void *file) {1141INTERCEPTOR(SIZE_T, fwrite, const void *p, usize size, usize nmemb, void *file) {
1108 // libc file streams can call user-supplied functions, see fopencookie.1142 // libc file streams can call user-supplied functions, see fopencookie.
1109 void *ctx;1143 void *ctx;
1110 COMMON_INTERCEPTOR_ENTER(ctx, fwrite, p, size, nmemb, file);1144 COMMON_INTERCEPTOR_ENTER(ctx, fwrite, p, size, nmemb, file);
...@@ -1255,6 +1289,12 @@ INTERCEPTOR(int, prctl, int option, unsigned long arg2, unsigned long arg3,...@@ -1255,6 +1289,12 @@ INTERCEPTOR(int, prctl, int option, unsigned long arg2, unsigned long arg3,
1255 static const int PR_SET_VMA = 0x53564d41;1289 static const int PR_SET_VMA = 0x53564d41;
1256 static const int PR_SCHED_CORE = 62;1290 static const int PR_SCHED_CORE = 62;
1257 static const int PR_SCHED_CORE_GET = 0;1291 static const int PR_SCHED_CORE_GET = 0;
1292 static const int PR_GET_PDEATHSIG = 2;
1293
1294# if !SANITIZER_ANDROID
1295 static const int PR_SET_SECCOMP = 22;
1296 static const int SECCOMP_MODE_FILTER = 2;
1297# endif
1258 if (option == PR_SET_VMA && arg2 == 0UL) {1298 if (option == PR_SET_VMA && arg2 == 0UL) {
1259 char *name = (char *)arg5;1299 char *name = (char *)arg5;
1260 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);1300 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
...@@ -1270,7 +1310,14 @@ INTERCEPTOR(int, prctl, int option, unsigned long arg2, unsigned long arg3,...@@ -1270,7 +1310,14 @@ INTERCEPTOR(int, prctl, int option, unsigned long arg2, unsigned long arg3,
1270 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strlen(name) + 1);1310 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strlen(name) + 1);
1271 } else if (res != -1 && option == PR_SCHED_CORE &&1311 } else if (res != -1 && option == PR_SCHED_CORE &&
1272 arg2 == PR_SCHED_CORE_GET) {1312 arg2 == PR_SCHED_CORE_GET) {
1273 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (u64*)(arg5), sizeof(u64));1313 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (u64 *)(arg5), sizeof(u64));
1314 } else if (res != -1 && option == PR_GET_PDEATHSIG) {
1315 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (u64 *)(arg2), sizeof(int));
1316# if SANITIZER_GLIBC
1317 } else if (res != -1 && option == PR_SET_SECCOMP &&
1318 arg2 == SECCOMP_MODE_FILTER) {
1319 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (u64 *)(arg3), struct_sock_fprog_sz);
1320# endif
1274 }1321 }
1275 return res;1322 return res;
1276}1323}
...@@ -2242,6 +2289,61 @@ INTERCEPTOR(int, pthread_getcpuclockid, uptr thread,...@@ -2242,6 +2289,61 @@ INTERCEPTOR(int, pthread_getcpuclockid, uptr thread,
2242#define INIT_CLOCK_GETCPUCLOCKID2289#define INIT_CLOCK_GETCPUCLOCKID
2243#endif2290#endif
22442291
2292#if SANITIZER_INTERCEPT_TIMER_CREATE
2293INTERCEPTOR(int, timer_create, __sanitizer_clockid_t clockid, void *sevp,
2294 __sanitizer_timer_t *timer) {
2295 void *ctx;
2296 COMMON_INTERCEPTOR_ENTER(ctx, timer_create, clockid, sevp, timer);
2297 int res = REAL(timer_create)(clockid, sevp, timer);
2298 if (!res && timer) {
2299 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, timer, sizeof *timer);
2300 }
2301 return res;
2302}
2303
2304INTERCEPTOR(int, timer_delete, __sanitizer_timer_t timer) {
2305 void *ctx;
2306 COMMON_INTERCEPTOR_ENTER(ctx, timer_delete, timer);
2307 int res = REAL(timer_delete)(timer);
2308 return res;
2309}
2310
2311INTERCEPTOR(int, timer_gettime, __sanitizer_timer_t timer,
2312 struct __sanitizer_itimerspec *curr_value) {
2313 void *ctx;
2314 COMMON_INTERCEPTOR_ENTER(ctx, timer_gettime, timer, curr_value);
2315 int res = REAL(timer_gettime)(timer, curr_value);
2316 if (!res && curr_value) {
2317 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, curr_value, sizeof *curr_value);
2318 }
2319 return res;
2320}
2321
2322INTERCEPTOR(int, timer_settime, __sanitizer_timer_t timer, int flags,
2323 const struct __sanitizer_itimerspec *new_value,
2324 struct __sanitizer_itimerspec *old_value) {
2325 void *ctx;
2326 COMMON_INTERCEPTOR_ENTER(ctx, timer_settime, timer, flags, new_value,
2327 old_value);
2328 int res = REAL(timer_settime)(timer, flags, new_value, old_value);
2329 if (!res) {
2330 if (new_value)
2331 COMMON_INTERCEPTOR_READ_RANGE(ctx, new_value, sizeof *new_value);
2332 if (old_value)
2333 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, old_value, sizeof *old_value);
2334 }
2335 return res;
2336}
2337
2338# define INIT_TIMER_CREATE \
2339 COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(timer_create, "GLIBC_2.3.3"); \
2340 COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(timer_delete, "GLIBC_2.3.3"); \
2341 COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(timer_gettime, "GLIBC_2.3.3"); \
2342 COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(timer_settime, "GLIBC_2.3.3");
2343#else
2344# define INIT_TIMER_CREATE
2345#endif
2346
2245#if SANITIZER_INTERCEPT_GETITIMER2347#if SANITIZER_INTERCEPT_GETITIMER
2246INTERCEPTOR(int, getitimer, int which, void *curr_value) {2348INTERCEPTOR(int, getitimer, int which, void *curr_value) {
2247 void *ctx;2349 void *ctx;
...@@ -2287,6 +2389,25 @@ INTERCEPTOR(int, setitimer, int which, const void *new_value, void *old_value) {...@@ -2287,6 +2389,25 @@ INTERCEPTOR(int, setitimer, int which, const void *new_value, void *old_value) {
2287#define INIT_GETITIMER2389#define INIT_GETITIMER
2288#endif2390#endif
22892391
2392#if SANITIZER_INTERCEPT_TIMESPEC_GET
2393INTERCEPTOR(int, timespec_get, struct __sanitizer_timespec *ts, int base) {
2394 void *ctx;
2395 COMMON_INTERCEPTOR_ENTER(ctx, timespec_get, ts, base);
2396 // We don't yet know if ts is addressable, so we use our own scratch buffer
2397 struct __sanitizer_timespec ts_local;
2398 int res = REAL(timespec_get)(&ts_local, base);
2399 if (res) {
2400 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ts,
2401 sizeof(struct __sanitizer_timespec));
2402 internal_memcpy(ts, &ts_local, sizeof(struct __sanitizer_timespec));
2403 }
2404 return res;
2405}
2406# define INIT_TIMESPEC_GET COMMON_INTERCEPT_FUNCTION(timespec_get);
2407#else
2408# define INIT_TIMESPEC_GET
2409#endif
2410
2290#if SANITIZER_INTERCEPT_GLOB2411#if SANITIZER_INTERCEPT_GLOB
2291static void unpoison_glob_t(void *ctx, __sanitizer_glob_t *pglob) {2412static void unpoison_glob_t(void *ctx, __sanitizer_glob_t *pglob) {
2292 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pglob, sizeof(*pglob));2413 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pglob, sizeof(*pglob));
...@@ -3427,23 +3548,27 @@ INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) {...@@ -3427,23 +3548,27 @@ INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) {
3427 COMMON_INTERCEPTOR_ENTER(ctx, ptrace, request, pid, addr, data);3548 COMMON_INTERCEPTOR_ENTER(ctx, ptrace, request, pid, addr, data);
3428 __sanitizer_iovec local_iovec;3549 __sanitizer_iovec local_iovec;
34293550
3430 if (data) {3551 void *data_arg = ptrace_data_arg(request, addr, data);
3552 if (data_arg) {
3431 if (request == ptrace_setregs) {3553 if (request == ptrace_setregs) {
3432 COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_regs_struct_sz);3554 COMMON_INTERCEPTOR_READ_RANGE(ctx, data_arg, struct_user_regs_struct_sz);
3433 } else if (request == ptrace_setfpregs) {3555 } else if (request == ptrace_setfpregs) {
3434 COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpregs_struct_sz);3556 COMMON_INTERCEPTOR_READ_RANGE(ctx, data_arg,
3557 struct_user_fpregs_struct_sz);
3435 } else if (request == ptrace_setfpxregs) {3558 } else if (request == ptrace_setfpxregs) {
3436 COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpxregs_struct_sz);3559 COMMON_INTERCEPTOR_READ_RANGE(ctx, data_arg,
3560 struct_user_fpxregs_struct_sz);
3437 } else if (request == ptrace_setvfpregs) {3561 } else if (request == ptrace_setvfpregs) {
3438 COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_vfpregs_struct_sz);3562 COMMON_INTERCEPTOR_READ_RANGE(ctx, data_arg,
3563 struct_user_vfpregs_struct_sz);
3439 } else if (request == ptrace_setsiginfo) {3564 } else if (request == ptrace_setsiginfo) {
3440 COMMON_INTERCEPTOR_READ_RANGE(ctx, data, siginfo_t_sz);3565 COMMON_INTERCEPTOR_READ_RANGE(ctx, data_arg, siginfo_t_sz);
34413566
3442 // Some kernel might zero the iovec::iov_base in case of invalid3567 // Some kernel might zero the iovec::iov_base in case of invalid
3443 // write access. In this case copy the invalid address for further3568 // write access. In this case copy the invalid address for further
3444 // inspection.3569 // inspection.
3445 } else if (request == ptrace_setregset || request == ptrace_getregset) {3570 } else if (request == ptrace_setregset || request == ptrace_getregset) {
3446 __sanitizer_iovec *iovec = (__sanitizer_iovec*)data;3571 __sanitizer_iovec *iovec = (__sanitizer_iovec *)data_arg;
3447 COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec, sizeof(*iovec));3572 COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec, sizeof(*iovec));
3448 local_iovec = *iovec;3573 local_iovec = *iovec;
3449 if (request == ptrace_setregset)3574 if (request == ptrace_setregset)
...@@ -3456,23 +3581,26 @@ INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) {...@@ -3456,23 +3581,26 @@ INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) {
3456 // https://github.com/google/sanitizers/issues/321.3581 // https://github.com/google/sanitizers/issues/321.
3457 uptr res = REAL(ptrace)(request, pid, addr, data);3582 uptr res = REAL(ptrace)(request, pid, addr, data);
34583583
3459 if (!res && data) {3584 if (!res && data_arg) {
3460 // Note that PEEK* requests assign different meaning to the return value.3585 // Note that PEEK* requests assign different meaning to the return value.
3461 // This function does not handle them (nor does it need to).3586 // This function does not handle them (nor does it need to).
3462 if (request == ptrace_getregs) {3587 if (request == ptrace_getregs) {
3463 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_regs_struct_sz);3588 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data_arg, struct_user_regs_struct_sz);
3464 } else if (request == ptrace_getfpregs) {3589 } else if (request == ptrace_getfpregs) {
3465 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpregs_struct_sz);3590 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data_arg,
3591 struct_user_fpregs_struct_sz);
3466 } else if (request == ptrace_getfpxregs) {3592 } else if (request == ptrace_getfpxregs) {
3467 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpxregs_struct_sz);3593 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data_arg,
3594 struct_user_fpxregs_struct_sz);
3468 } else if (request == ptrace_getvfpregs) {3595 } else if (request == ptrace_getvfpregs) {
3469 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_vfpregs_struct_sz);3596 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data_arg,
3597 struct_user_vfpregs_struct_sz);
3470 } else if (request == ptrace_getsiginfo) {3598 } else if (request == ptrace_getsiginfo) {
3471 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, siginfo_t_sz);3599 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data_arg, siginfo_t_sz);
3472 } else if (request == ptrace_geteventmsg) {3600 } else if (request == ptrace_geteventmsg) {
3473 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, sizeof(unsigned long));3601 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data_arg, sizeof(unsigned long));
3474 } else if (request == ptrace_getregset) {3602 } else if (request == ptrace_getregset) {
3475 __sanitizer_iovec *iovec = (__sanitizer_iovec*)data;3603 __sanitizer_iovec *iovec = (__sanitizer_iovec *)data_arg;
3476 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iovec, sizeof(*iovec));3604 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iovec, sizeof(*iovec));
3477 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, local_iovec.iov_base,3605 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, local_iovec.iov_base,
3478 local_iovec.iov_len);3606 local_iovec.iov_len);
...@@ -6425,12 +6553,12 @@ static void MlockIsUnsupported() {...@@ -6425,12 +6553,12 @@ static void MlockIsUnsupported() {
6425 SanitizerToolName);6553 SanitizerToolName);
6426}6554}
64276555
6428INTERCEPTOR(int, mlock, const void *addr, uptr len) {6556INTERCEPTOR(int, mlock, const void *addr, usize len) {
6429 MlockIsUnsupported();6557 MlockIsUnsupported();
6430 return 0;6558 return 0;
6431}6559}
64326560
6433INTERCEPTOR(int, munlock, const void *addr, uptr len) {6561INTERCEPTOR(int, munlock, const void *addr, usize len) {
6434 MlockIsUnsupported();6562 MlockIsUnsupported();
6435 return 0;6563 return 0;
6436}6564}
...@@ -8823,83 +8951,6 @@ INTERCEPTOR(char *, RMD160Data, u8 *data, SIZE_T len, char *buf) {...@@ -8823,83 +8951,6 @@ INTERCEPTOR(char *, RMD160Data, u8 *data, SIZE_T len, char *buf) {
8823#define INIT_RMD1608951#define INIT_RMD160
8824#endif8952#endif
88258953
8826#if SANITIZER_INTERCEPT_MD5
8827INTERCEPTOR(void, MD5Init, void *context) {
8828 void *ctx;
8829 COMMON_INTERCEPTOR_ENTER(ctx, MD5Init, context);
8830 REAL(MD5Init)(context);
8831 if (context)
8832 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD5_CTX_sz);
8833}
8834
8835INTERCEPTOR(void, MD5Update, void *context, const unsigned char *data,
8836 unsigned int len) {
8837 void *ctx;
8838 COMMON_INTERCEPTOR_ENTER(ctx, MD5Update, context, data, len);
8839 if (data && len > 0)
8840 COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
8841 if (context)
8842 COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD5_CTX_sz);
8843 REAL(MD5Update)(context, data, len);
8844 if (context)
8845 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD5_CTX_sz);
8846}
8847
8848INTERCEPTOR(void, MD5Final, unsigned char digest[16], void *context) {
8849 void *ctx;
8850 COMMON_INTERCEPTOR_ENTER(ctx, MD5Final, digest, context);
8851 if (context)
8852 COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD5_CTX_sz);
8853 REAL(MD5Final)(digest, context);
8854 if (digest)
8855 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(unsigned char) * 16);
8856}
8857
8858INTERCEPTOR(char *, MD5End, void *context, char *buf) {
8859 void *ctx;
8860 COMMON_INTERCEPTOR_ENTER(ctx, MD5End, context, buf);
8861 if (context)
8862 COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD5_CTX_sz);
8863 char *ret = REAL(MD5End)(context, buf);
8864 if (ret)
8865 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD5_return_length);
8866 return ret;
8867}
8868
8869INTERCEPTOR(char *, MD5File, const char *filename, char *buf) {
8870 void *ctx;
8871 COMMON_INTERCEPTOR_ENTER(ctx, MD5File, filename, buf);
8872 if (filename)
8873 COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
8874 char *ret = REAL(MD5File)(filename, buf);
8875 if (ret)
8876 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD5_return_length);
8877 return ret;
8878}
8879
8880INTERCEPTOR(char *, MD5Data, const unsigned char *data, unsigned int len,
8881 char *buf) {
8882 void *ctx;
8883 COMMON_INTERCEPTOR_ENTER(ctx, MD5Data, data, len, buf);
8884 if (data && len > 0)
8885 COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
8886 char *ret = REAL(MD5Data)(data, len, buf);
8887 if (ret)
8888 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD5_return_length);
8889 return ret;
8890}
8891
8892#define INIT_MD5 \
8893 COMMON_INTERCEPT_FUNCTION(MD5Init); \
8894 COMMON_INTERCEPT_FUNCTION(MD5Update); \
8895 COMMON_INTERCEPT_FUNCTION(MD5Final); \
8896 COMMON_INTERCEPT_FUNCTION(MD5End); \
8897 COMMON_INTERCEPT_FUNCTION(MD5File); \
8898 COMMON_INTERCEPT_FUNCTION(MD5Data)
8899#else
8900#define INIT_MD5
8901#endif
8902
8903#if SANITIZER_INTERCEPT_FSEEK8954#if SANITIZER_INTERCEPT_FSEEK
8904INTERCEPTOR(int, fseek, __sanitizer_FILE *stream, long int offset, int whence) {8955INTERCEPTOR(int, fseek, __sanitizer_FILE *stream, long int offset, int whence) {
8905 void *ctx;8956 void *ctx;
...@@ -9030,107 +9081,6 @@ INTERCEPTOR(char *, MD2Data, const unsigned char *data, unsigned int len,...@@ -9030,107 +9081,6 @@ INTERCEPTOR(char *, MD2Data, const unsigned char *data, unsigned int len,
9030#define INIT_MD29081#define INIT_MD2
9031#endif9082#endif
90329083
9033#if SANITIZER_INTERCEPT_SHA2
9034#define SHA2_INTERCEPTORS(LEN, SHA2_STATE_T) \
9035 INTERCEPTOR(void, SHA##LEN##_Init, void *context) { \
9036 void *ctx; \
9037 COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_Init, context); \
9038 REAL(SHA##LEN##_Init)(context); \
9039 if (context) \
9040 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
9041 } \
9042 INTERCEPTOR(void, SHA##LEN##_Update, void *context, \
9043 const u8 *data, SIZE_T len) { \
9044 void *ctx; \
9045 COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_Update, context, data, len); \
9046 if (data && len > 0) \
9047 COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len); \
9048 if (context) \
9049 COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
9050 REAL(SHA##LEN##_Update)(context, data, len); \
9051 if (context) \
9052 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
9053 } \
9054 INTERCEPTOR(void, SHA##LEN##_Final, u8 digest[LEN/8], \
9055 void *context) { \
9056 void *ctx; \
9057 CHECK_EQ(SHA##LEN##_digest_length, LEN/8); \
9058 COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_Final, digest, context); \
9059 if (context) \
9060 COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
9061 REAL(SHA##LEN##_Final)(digest, context); \
9062 if (digest) \
9063 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, \
9064 sizeof(digest[0]) * \
9065 SHA##LEN##_digest_length); \
9066 } \
9067 INTERCEPTOR(char *, SHA##LEN##_End, void *context, char *buf) { \
9068 void *ctx; \
9069 COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_End, context, buf); \
9070 if (context) \
9071 COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
9072 char *ret = REAL(SHA##LEN##_End)(context, buf); \
9073 if (ret) \
9074 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \
9075 return ret; \
9076 } \
9077 INTERCEPTOR(char *, SHA##LEN##_File, const char *filename, char *buf) { \
9078 void *ctx; \
9079 COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_File, filename, buf); \
9080 if (filename) \
9081 COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);\
9082 char *ret = REAL(SHA##LEN##_File)(filename, buf); \
9083 if (ret) \
9084 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \
9085 return ret; \
9086 } \
9087 INTERCEPTOR(char *, SHA##LEN##_FileChunk, const char *filename, char *buf, \
9088 OFF_T offset, OFF_T length) { \
9089 void *ctx; \
9090 COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_FileChunk, filename, buf, offset, \
9091 length); \
9092 if (filename) \
9093 COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);\
9094 char *ret = REAL(SHA##LEN##_FileChunk)(filename, buf, offset, length); \
9095 if (ret) \
9096 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \
9097 return ret; \
9098 } \
9099 INTERCEPTOR(char *, SHA##LEN##_Data, u8 *data, SIZE_T len, char *buf) { \
9100 void *ctx; \
9101 COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_Data, data, len, buf); \
9102 if (data && len > 0) \
9103 COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len); \
9104 char *ret = REAL(SHA##LEN##_Data)(data, len, buf); \
9105 if (ret) \
9106 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \
9107 return ret; \
9108 }
9109
9110SHA2_INTERCEPTORS(224, u32)
9111SHA2_INTERCEPTORS(256, u32)
9112SHA2_INTERCEPTORS(384, u64)
9113SHA2_INTERCEPTORS(512, u64)
9114
9115#define INIT_SHA2_INTECEPTORS(LEN) \
9116 COMMON_INTERCEPT_FUNCTION(SHA##LEN##_Init); \
9117 COMMON_INTERCEPT_FUNCTION(SHA##LEN##_Update); \
9118 COMMON_INTERCEPT_FUNCTION(SHA##LEN##_Final); \
9119 COMMON_INTERCEPT_FUNCTION(SHA##LEN##_End); \
9120 COMMON_INTERCEPT_FUNCTION(SHA##LEN##_File); \
9121 COMMON_INTERCEPT_FUNCTION(SHA##LEN##_FileChunk); \
9122 COMMON_INTERCEPT_FUNCTION(SHA##LEN##_Data)
9123
9124#define INIT_SHA2 \
9125 INIT_SHA2_INTECEPTORS(224); \
9126 INIT_SHA2_INTECEPTORS(256); \
9127 INIT_SHA2_INTECEPTORS(384); \
9128 INIT_SHA2_INTECEPTORS(512)
9129#undef SHA2_INTERCEPTORS
9130#else
9131#define INIT_SHA2
9132#endif
9133
9134#if SANITIZER_INTERCEPT_VIS9084#if SANITIZER_INTERCEPT_VIS
9135INTERCEPTOR(char *, vis, char *dst, int c, int flag, int nextc) {9085INTERCEPTOR(char *, vis, char *dst, int c, int flag, int nextc) {
9136 void *ctx;9086 void *ctx;
...@@ -9980,7 +9930,7 @@ INTERCEPTOR(SSIZE_T, getrandom, void *buf, SIZE_T buflen, unsigned int flags) {...@@ -9980,7 +9930,7 @@ INTERCEPTOR(SSIZE_T, getrandom, void *buf, SIZE_T buflen, unsigned int flags) {
9980 void *ctx;9930 void *ctx;
9981 COMMON_INTERCEPTOR_ENTER(ctx, getrandom, buf, buflen, flags);9931 COMMON_INTERCEPTOR_ENTER(ctx, getrandom, buf, buflen, flags);
9982 // If GRND_NONBLOCK is set in the flags, it is non blocking.9932 // If GRND_NONBLOCK is set in the flags, it is non blocking.
9983 static const int grnd_nonblock = 1; 9933 static const int grnd_nonblock = 1;
9984 SSIZE_T n;9934 SSIZE_T n;
9985 if ((flags & grnd_nonblock))9935 if ((flags & grnd_nonblock))
9986 n = REAL(getrandom)(buf, buflen, flags);9936 n = REAL(getrandom)(buf, buflen, flags);
...@@ -10296,6 +10246,23 @@ INTERCEPTOR(SSIZE_T, pwritev2, int fd, __sanitizer_iovec *iov, int iovcnt,...@@ -10296,6 +10246,23 @@ INTERCEPTOR(SSIZE_T, pwritev2, int fd, __sanitizer_iovec *iov, int iovcnt,
10296#define INIT_PWRITEV210246#define INIT_PWRITEV2
10297#endif10247#endif
1029810248
10249#if SANITIZER_INTERCEPT_FREADLINK
10250INTERCEPTOR(SSIZE_T, freadlink, int fd, char *buf, SIZE_T bufsiz) {
10251 void *ctx;
10252 COMMON_INTERCEPTOR_ENTER(ctx, freadlink, fd, buf, bufsiz);
10253 COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
10254 SSIZE_T res = REAL(freadlink)(fd, buf, bufsiz);
10255 if (res > 0)
10256 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, res);
10257 if (res >= 0 && fd > 0)
10258 COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
10259 return res;
10260}
10261# define INIT_FREADLINK COMMON_INTERCEPT_FUNCTION(freadlink)
10262#else
10263# define INIT_FREADLINK
10264#endif
10265
10299#include "sanitizer_common_interceptors_netbsd_compat.inc"10266#include "sanitizer_common_interceptors_netbsd_compat.inc"
1030010267
10301namespace __sanitizer {10268namespace __sanitizer {
...@@ -10373,8 +10340,10 @@ static void InitializeCommonInterceptors() {...@@ -10373,8 +10340,10 @@ static void InitializeCommonInterceptors() {
10373 INIT_SETPWENT;10340 INIT_SETPWENT;
10374 INIT_CLOCK_GETTIME;10341 INIT_CLOCK_GETTIME;
10375 INIT_CLOCK_GETCPUCLOCKID;10342 INIT_CLOCK_GETCPUCLOCKID;
10343 INIT_TIMER_CREATE;
10376 INIT_GETITIMER;10344 INIT_GETITIMER;
10377 INIT_TIME;10345 INIT_TIME;
10346 INIT_TIMESPEC_GET;
10378 INIT_GLOB;10347 INIT_GLOB;
10379 INIT_GLOB64;10348 INIT_GLOB64;
10380 INIT___B64_TO;10349 INIT___B64_TO;
...@@ -10588,10 +10557,8 @@ static void InitializeCommonInterceptors() {...@@ -10588,10 +10557,8 @@ static void InitializeCommonInterceptors() {
10588 INIT_SHA1;10557 INIT_SHA1;
10589 INIT_MD4;10558 INIT_MD4;
10590 INIT_RMD160;10559 INIT_RMD160;
10591 INIT_MD5;
10592 INIT_FSEEK;10560 INIT_FSEEK;
10593 INIT_MD2;10561 INIT_MD2;
10594 INIT_SHA2;
10595 INIT_VIS;10562 INIT_VIS;
10596 INIT_CDB;10563 INIT_CDB;
10597 INIT_GETFSENT;10564 INIT_GETFSENT;
...@@ -10617,6 +10584,7 @@ static void InitializeCommonInterceptors() {...@@ -10617,6 +10584,7 @@ static void InitializeCommonInterceptors() {
10617 INIT_CPUSET_GETAFFINITY;10584 INIT_CPUSET_GETAFFINITY;
10618 INIT_PREADV2;10585 INIT_PREADV2;
10619 INIT_PWRITEV2;10586 INIT_PWRITEV2;
10587 INIT_FREADLINK;
1062010588
10621 INIT___PRINTF_CHK;10589 INIT___PRINTF_CHK;
10622}10590}
lib/tsan/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc+17-17
...@@ -82,7 +82,7 @@...@@ -82,7 +82,7 @@
82#endif82#endif
8383
84#if SANITIZER_INTERCEPT_MEMSET84#if SANITIZER_INTERCEPT_MEMSET
85INTERCEPTOR(void *, memset, void *dst, int v, uptr size) {85INTERCEPTOR(void *, memset, void *dst, int v, usize size) {
86 void *ctx;86 void *ctx;
87 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size);87 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size);
88}88}
...@@ -93,7 +93,7 @@ INTERCEPTOR(void *, memset, void *dst, int v, uptr size) {...@@ -93,7 +93,7 @@ INTERCEPTOR(void *, memset, void *dst, int v, uptr size) {
93#endif93#endif
9494
95#if SANITIZER_INTERCEPT_MEMMOVE95#if SANITIZER_INTERCEPT_MEMMOVE
96INTERCEPTOR(void *, memmove, void *dst, const void *src, uptr size) {96INTERCEPTOR(void *, memmove, void *dst, const void *src, usize size) {
97 void *ctx;97 void *ctx;
98 COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size);98 COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size);
99}99}
...@@ -104,7 +104,7 @@ INTERCEPTOR(void *, memmove, void *dst, const void *src, uptr size) {...@@ -104,7 +104,7 @@ INTERCEPTOR(void *, memmove, void *dst, const void *src, uptr size) {
104#endif104#endif
105105
106#if SANITIZER_INTERCEPT_MEMCPY106#if SANITIZER_INTERCEPT_MEMCPY
107INTERCEPTOR(void *, memcpy, void *dst, const void *src, uptr size) {107INTERCEPTOR(void *, memcpy, void *dst, const void *src, usize size) {
108 // On OS X, calling internal_memcpy here will cause memory corruptions,108 // On OS X, calling internal_memcpy here will cause memory corruptions,
109 // because memcpy and memmove are actually aliases of the same109 // because memcpy and memmove are actually aliases of the same
110 // implementation. We need to use internal_memmove here.110 // implementation. We need to use internal_memmove here.
...@@ -133,63 +133,63 @@ INTERCEPTOR(void *, memcpy, void *dst, const void *src, uptr size) {...@@ -133,63 +133,63 @@ INTERCEPTOR(void *, memcpy, void *dst, const void *src, uptr size) {
133#endif133#endif
134134
135#if SANITIZER_INTERCEPT_AEABI_MEM135#if SANITIZER_INTERCEPT_AEABI_MEM
136INTERCEPTOR(void *, __aeabi_memmove, void *to, const void *from, uptr size) {136INTERCEPTOR(void *, __aeabi_memmove, void *to, const void *from, usize size) {
137 void *ctx;137 void *ctx;
138 COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);138 COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
139}139}
140140
141INTERCEPTOR(void *, __aeabi_memmove4, void *to, const void *from, uptr size) {141INTERCEPTOR(void *, __aeabi_memmove4, void *to, const void *from, usize size) {
142 void *ctx;142 void *ctx;
143 COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);143 COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
144}144}
145145
146INTERCEPTOR(void *, __aeabi_memmove8, void *to, const void *from, uptr size) {146INTERCEPTOR(void *, __aeabi_memmove8, void *to, const void *from, usize size) {
147 void *ctx;147 void *ctx;
148 COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);148 COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
149}149}
150150
151INTERCEPTOR(void *, __aeabi_memcpy, void *to, const void *from, uptr size) {151INTERCEPTOR(void *, __aeabi_memcpy, void *to, const void *from, usize size) {
152 void *ctx;152 void *ctx;
153 COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);153 COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
154}154}
155155
156INTERCEPTOR(void *, __aeabi_memcpy4, void *to, const void *from, uptr size) {156INTERCEPTOR(void *, __aeabi_memcpy4, void *to, const void *from, usize size) {
157 void *ctx;157 void *ctx;
158 COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);158 COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
159}159}
160160
161INTERCEPTOR(void *, __aeabi_memcpy8, void *to, const void *from, uptr size) {161INTERCEPTOR(void *, __aeabi_memcpy8, void *to, const void *from, usize size) {
162 void *ctx;162 void *ctx;
163 COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);163 COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
164}164}
165165
166// Note the argument order.166// Note the argument order.
167INTERCEPTOR(void *, __aeabi_memset, void *block, uptr size, int c) {167INTERCEPTOR(void *, __aeabi_memset, void *block, usize size, int c) {
168 void *ctx;168 void *ctx;
169 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);169 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
170}170}
171171
172INTERCEPTOR(void *, __aeabi_memset4, void *block, uptr size, int c) {172INTERCEPTOR(void *, __aeabi_memset4, void *block, usize size, int c) {
173 void *ctx;173 void *ctx;
174 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);174 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
175}175}
176176
177INTERCEPTOR(void *, __aeabi_memset8, void *block, uptr size, int c) {177INTERCEPTOR(void *, __aeabi_memset8, void *block, usize size, int c) {
178 void *ctx;178 void *ctx;
179 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);179 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
180}180}
181181
182INTERCEPTOR(void *, __aeabi_memclr, void *block, uptr size) {182INTERCEPTOR(void *, __aeabi_memclr, void *block, usize size) {
183 void *ctx;183 void *ctx;
184 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);184 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
185}185}
186186
187INTERCEPTOR(void *, __aeabi_memclr4, void *block, uptr size) {187INTERCEPTOR(void *, __aeabi_memclr4, void *block, usize size) {
188 void *ctx;188 void *ctx;
189 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);189 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
190}190}
191191
192INTERCEPTOR(void *, __aeabi_memclr8, void *block, uptr size) {192INTERCEPTOR(void *, __aeabi_memclr8, void *block, usize size) {
193 void *ctx;193 void *ctx;
194 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);194 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
195}195}
...@@ -212,7 +212,7 @@ INTERCEPTOR(void *, __aeabi_memclr8, void *block, uptr size) {...@@ -212,7 +212,7 @@ INTERCEPTOR(void *, __aeabi_memclr8, void *block, uptr size) {
212#endif // SANITIZER_INTERCEPT_AEABI_MEM212#endif // SANITIZER_INTERCEPT_AEABI_MEM
213213
214#if SANITIZER_INTERCEPT___BZERO214#if SANITIZER_INTERCEPT___BZERO
215INTERCEPTOR(void *, __bzero, void *block, uptr size) {215INTERCEPTOR(void *, __bzero, void *block, usize size) {
216 void *ctx;216 void *ctx;
217 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);217 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
218}218}
...@@ -222,7 +222,7 @@ INTERCEPTOR(void *, __bzero, void *block, uptr size) {...@@ -222,7 +222,7 @@ INTERCEPTOR(void *, __bzero, void *block, uptr size) {
222#endif // SANITIZER_INTERCEPT___BZERO222#endif // SANITIZER_INTERCEPT___BZERO
223223
224#if SANITIZER_INTERCEPT_BZERO224#if SANITIZER_INTERCEPT_BZERO
225INTERCEPTOR(void *, bzero, void *block, uptr size) {225INTERCEPTOR(void *, bzero, void *block, usize size) {
226 void *ctx;226 void *ctx;
227 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);227 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
228}228}
lib/tsan/sanitizer_common/sanitizer_common_interceptors_vfork_aarch64.inc.S created+48
...@@ -0,0 +1,48 @@
1#if defined(__aarch64__) && defined(__linux__)
2
3#include "sanitizer_common/sanitizer_asm.h"
4#include "builtins/assembly.h"
5
6ASM_HIDDEN(COMMON_INTERCEPTOR_SPILL_AREA)
7
8.comm _ZN14__interception10real_vforkE,8,8
9.globl ASM_WRAPPER_NAME(vfork)
10ASM_TYPE_FUNCTION(ASM_WRAPPER_NAME(vfork))
11ASM_WRAPPER_NAME(vfork):
12 // Save x30 in the off-stack spill area.
13 hint #25 // paciasp
14 stp xzr, x30, [sp, #-16]!
15 bl COMMON_INTERCEPTOR_SPILL_AREA
16 ldp xzr, x30, [sp], 16
17 str x30, [x0]
18
19 // Call real vfork. This may return twice. User code that runs between the first and the second return
20 // may clobber the stack frame of the interceptor; that's why it does not have a frame.
21 adrp x0, _ZN14__interception10real_vforkE
22 ldr x0, [x0, :lo12:_ZN14__interception10real_vforkE]
23 blr x0
24
25 stp x0, xzr, [sp, #-16]!
26 cmp x0, #0
27 b.eq .L_exit
28
29 // x0 != 0 => parent process. Clear stack shadow.
30 add x0, sp, #16
31 bl COMMON_INTERCEPTOR_HANDLE_VFORK
32
33.L_exit:
34 // Restore x30.
35 bl COMMON_INTERCEPTOR_SPILL_AREA
36 ldr x30, [x0]
37 ldp x0, xzr, [sp], 16
38 hint #29 // autiasp
39
40 ret
41ASM_SIZE(vfork)
42
43ASM_INTERCEPTOR_TRAMPOLINE(vfork)
44ASM_TRAMPOLINE_ALIAS(vfork, vfork)
45
46GNU_PROPERTY_BTI_PAC
47
48#endif
lib/tsan/sanitizer_common/sanitizer_common_interceptors_vfork_arm.inc.S created+49
...@@ -0,0 +1,49 @@
1#if defined(__arm__) && defined(__linux__)
2
3#include "sanitizer_common/sanitizer_asm.h"
4
5ASM_HIDDEN(COMMON_INTERCEPTOR_SPILL_AREA)
6
7.comm _ZN14__interception10real_vforkE,4,4
8.globl ASM_WRAPPER_NAME(vfork)
9ASM_TYPE_FUNCTION(ASM_WRAPPER_NAME(vfork))
10ASM_WRAPPER_NAME(vfork):
11 // Save LR in the off-stack spill area.
12 push {r4, lr}
13 bl COMMON_INTERCEPTOR_SPILL_AREA
14 pop {r4, lr}
15 str lr, [r0]
16
17 // Call real vfork. This may return twice. User code that runs between the first and the second return
18 // may clobber the stack frame of the interceptor; that's why it does not have a frame.
19 ldr r0, .LCPI0_0
20.LPC0_0:
21 ldr r0, [pc, r0]
22 mov lr, pc
23 bx r0
24
25 push {r0, r4}
26 cmp r0, #0
27 beq .L_exit
28
29 // r0 != 0 => parent process. Clear stack shadow.
30 add r0, sp, #8
31 bl COMMON_INTERCEPTOR_HANDLE_VFORK
32
33.L_exit:
34 // Restore LR.
35 bl COMMON_INTERCEPTOR_SPILL_AREA
36 ldr lr, [r0]
37 pop {r0, r4}
38
39 mov pc, lr
40
41.LCPI0_0:
42 .long _ZN14__interception10real_vforkE - (.LPC0_0+8)
43
44ASM_SIZE(vfork)
45
46ASM_INTERCEPTOR_TRAMPOLINE(vfork)
47ASM_TRAMPOLINE_ALIAS(vfork, vfork)
48
49#endif
lib/tsan/sanitizer_common/sanitizer_common_interceptors_vfork_i386.inc.S created+64
...@@ -0,0 +1,64 @@
1#if defined(__i386__) && defined(__linux__)
2
3#include "sanitizer_common/sanitizer_asm.h"
4
5.comm _ZN14__interception10real_vforkE,4,4
6.globl ASM_WRAPPER_NAME(vfork)
7ASM_TYPE_FUNCTION(ASM_WRAPPER_NAME(vfork))
8ASM_WRAPPER_NAME(vfork):
9 _CET_ENDBR
10 // Store return address in the spill area and tear down the stack frame.
11 sub $12, %esp
12 call COMMON_INTERCEPTOR_SPILL_AREA
13 mov 12(%esp), %ecx
14 mov %ecx, (%eax)
15 add $16, %esp
16
17 call .L0$pb
18.L0$pb:
19 pop %eax
20.Ltmp0:
21 add $_GLOBAL_OFFSET_TABLE_+(.Ltmp0-.L0$pb), %eax
22 call *_ZN14__interception10real_vforkE@GOTOFF(%eax)
23
24 // Restore the stack frame.
25 // 12(%esp) return address
26 // 8(%esp) spill %ebx
27 // 4(%esp) spill REAL(vfork) return value
28 // (%esp) call frame (arg0) for __*_handle_vfork
29 sub $16, %esp
30 mov %ebx, 8(%esp)
31 mov %eax, 4(%esp)
32
33 // Form GOT address in %ebx.
34 call .L1$pb
35.L1$pb:
36 pop %ebx
37.Ltmp1:
38 add $_GLOBAL_OFFSET_TABLE_+(.Ltmp1-.L1$pb), %ebx
39
40 // Restore original return address.
41 call COMMON_INTERCEPTOR_SPILL_AREA
42 mov (%eax), %ecx
43 mov %ecx, 12(%esp)
44 mov 4(%esp), %eax
45
46 // Call handle_vfork in the parent process (%rax != 0).
47 test %eax, %eax
48 je .L_exit
49
50 lea 16(%esp), %ecx
51 mov %ecx, (%esp)
52 call COMMON_INTERCEPTOR_HANDLE_VFORK@PLT
53
54.L_exit:
55 mov 4(%esp), %eax
56 mov 8(%esp), %ebx
57 add $12, %esp
58 ret
59ASM_SIZE(vfork)
60
61ASM_INTERCEPTOR_TRAMPOLINE(vfork)
62ASM_TRAMPOLINE_ALIAS(vfork, vfork)
63
64#endif
lib/tsan/sanitizer_common/sanitizer_common_interceptors_vfork_loongarch64.inc.S created+57
...@@ -0,0 +1,57 @@
1#if defined(__loongarch_lp64) && defined(__linux__)
2
3#include "sanitizer_common/sanitizer_asm.h"
4
5ASM_HIDDEN(COMMON_INTERCEPTOR_SPILL_AREA)
6ASM_HIDDEN(_ZN14__interception10real_vforkE)
7
8.text
9.globl ASM_WRAPPER_NAME(vfork)
10ASM_TYPE_FUNCTION(ASM_WRAPPER_NAME(vfork))
11ASM_WRAPPER_NAME(vfork):
12 // Save ra in the off-stack spill area.
13 // allocate space on stack
14 addi.d $sp, $sp, -16
15 // store $ra value
16 st.d $ra, $sp, 8
17 bl COMMON_INTERCEPTOR_SPILL_AREA
18 // restore previous values from stack
19 ld.d $ra, $sp, 8
20 // adjust stack
21 addi.d $sp, $sp, 16
22 // store $ra by $a0
23 st.d $ra, $a0, 0
24
25 // Call real vfork. This may return twice. User code that runs between the first and the second return
26 // may clobber the stack frame of the interceptor; that's why it does not have a frame.
27 la.local $a0, _ZN14__interception10real_vforkE
28 ld.d $a0, $a0, 0
29 jirl $ra, $a0, 0
30
31 // adjust stack
32 addi.d $sp, $sp, -16
33 // store $a0 by adjusted stack
34 st.d $a0, $sp, 8
35 // jump to exit label if $a0 is 0
36 beqz $a0, .L_exit
37
38 // $a0 != 0 => parent process. Clear stack shadow.
39 // put old $sp to $a0
40 addi.d $a0, $sp, 16
41 bl %plt(COMMON_INTERCEPTOR_HANDLE_VFORK)
42
43.L_exit:
44 // Restore $ra
45 bl COMMON_INTERCEPTOR_SPILL_AREA
46 ld.d $ra, $a0, 0
47 // load value by stack
48 ld.d $a0, $sp, 8
49 // adjust stack
50 addi.d $sp, $sp, 16
51 jr $ra
52ASM_SIZE(vfork)
53
54ASM_INTERCEPTOR_TRAMPOLINE(vfork)
55ASM_TRAMPOLINE_ALIAS(vfork, vfork)
56
57#endif
lib/tsan/sanitizer_common/sanitizer_common_interceptors_vfork_riscv64.inc.S created+56
...@@ -0,0 +1,56 @@
1#if (defined(__riscv) && (__riscv_xlen == 64)) && defined(__linux__)
2
3#include "sanitizer_common/sanitizer_asm.h"
4
5ASM_HIDDEN(COMMON_INTERCEPTOR_SPILL_AREA)
6
7.comm _ZN14__interception10real_vforkE,8,8
8.globl ASM_WRAPPER_NAME(vfork)
9ASM_TYPE_FUNCTION(ASM_WRAPPER_NAME(vfork))
10ASM_WRAPPER_NAME(vfork):
11 // Save ra in the off-stack spill area.
12 // allocate space on stack
13 addi sp, sp, -16
14 // store ra value
15 sd ra, 8(sp)
16 call COMMON_INTERCEPTOR_SPILL_AREA
17 // restore previous values from stack
18 ld ra, 8(sp)
19 // adjust stack
20 addi sp, sp, 16
21 // store ra by x10
22 sd ra, 0(x10)
23
24 // Call real vfork. This may return twice. User code that runs between the first and the second return
25 // may clobber the stack frame of the interceptor; that's why it does not have a frame.
26 la x10, _ZN14__interception10real_vforkE
27 ld x10, 0(x10)
28 jalr x10
29
30 // adjust stack
31 addi sp, sp, -16
32 // store x10 by adjusted stack
33 sd x10, 8(sp)
34 // jump to exit label if x10 is 0
35 beqz x10, .L_exit
36
37 // x0 != 0 => parent process. Clear stack shadow.
38 // put old sp to x10
39 addi x10, sp, 16
40 call COMMON_INTERCEPTOR_HANDLE_VFORK
41
42.L_exit:
43 // Restore ra
44 call COMMON_INTERCEPTOR_SPILL_AREA
45 ld ra, 0(x10)
46 // load value by stack
47 ld x10, 8(sp)
48 // adjust stack
49 addi sp, sp, 16
50 ret
51ASM_SIZE(vfork)
52
53ASM_INTERCEPTOR_TRAMPOLINE(vfork)
54ASM_TRAMPOLINE_ALIAS(vfork, vfork)
55
56#endif
lib/tsan/sanitizer_common/sanitizer_common_interceptors_vfork_x86_64.inc.S created+42
...@@ -0,0 +1,42 @@
1#if defined(__x86_64__) && defined(__linux__)
2
3#include "sanitizer_common/sanitizer_asm.h"
4
5.comm _ZN14__interception10real_vforkE,8,8
6.globl ASM_WRAPPER_NAME(vfork)
7ASM_TYPE_FUNCTION(ASM_WRAPPER_NAME(vfork))
8ASM_WRAPPER_NAME(vfork):
9 _CET_ENDBR
10 // Store return address in the spill area and tear down the stack frame.
11 push %rcx
12 call COMMON_INTERCEPTOR_SPILL_AREA
13 pop %rcx
14 pop %rdi
15 mov %rdi, (%rax)
16
17 call *_ZN14__interception10real_vforkE(%rip)
18
19 // Restore return address from the spill area.
20 push %rcx
21 push %rax
22 call COMMON_INTERCEPTOR_SPILL_AREA
23 mov (%rax), %rdx
24 mov %rdx, 8(%rsp)
25 mov (%rsp), %rax
26
27 // Call handle_vfork in the parent process (%rax != 0).
28 test %rax, %rax
29 je .L_exit
30
31 lea 16(%rsp), %rdi
32 call COMMON_INTERCEPTOR_HANDLE_VFORK@PLT
33
34.L_exit:
35 pop %rax
36 ret
37ASM_SIZE(ASM_WRAPPER_NAME(vfork))
38
39ASM_INTERCEPTOR_TRAMPOLINE(vfork)
40ASM_TRAMPOLINE_ALIAS(vfork, vfork)
41
42#endif
lib/tsan/sanitizer_common/sanitizer_common_interface.inc+8
...@@ -10,6 +10,7 @@...@@ -10,6 +10,7 @@
10INTERFACE_FUNCTION(__sanitizer_acquire_crash_state)10INTERFACE_FUNCTION(__sanitizer_acquire_crash_state)
11INTERFACE_FUNCTION(__sanitizer_annotate_contiguous_container)11INTERFACE_FUNCTION(__sanitizer_annotate_contiguous_container)
12INTERFACE_FUNCTION(__sanitizer_annotate_double_ended_contiguous_container)12INTERFACE_FUNCTION(__sanitizer_annotate_double_ended_contiguous_container)
13INTERFACE_FUNCTION(__sanitizer_copy_contiguous_container_annotations)
13INTERFACE_FUNCTION(__sanitizer_contiguous_container_find_bad_address)14INTERFACE_FUNCTION(__sanitizer_contiguous_container_find_bad_address)
14INTERFACE_FUNCTION(15INTERFACE_FUNCTION(
15 __sanitizer_double_ended_contiguous_container_find_bad_address)16 __sanitizer_double_ended_contiguous_container_find_bad_address)
...@@ -22,6 +23,7 @@ INTERFACE_FUNCTION(__sanitizer_verify_double_ended_contiguous_container)...@@ -22,6 +23,7 @@ INTERFACE_FUNCTION(__sanitizer_verify_double_ended_contiguous_container)
22INTERFACE_WEAK_FUNCTION(__sanitizer_on_print)23INTERFACE_WEAK_FUNCTION(__sanitizer_on_print)
23INTERFACE_WEAK_FUNCTION(__sanitizer_report_error_summary)24INTERFACE_WEAK_FUNCTION(__sanitizer_report_error_summary)
24INTERFACE_WEAK_FUNCTION(__sanitizer_sandbox_on_notify)25INTERFACE_WEAK_FUNCTION(__sanitizer_sandbox_on_notify)
26INTERFACE_WEAK_FUNCTION(__sanitizer_get_dtls_size)
25// Sanitizer weak hooks27// Sanitizer weak hooks
26INTERFACE_WEAK_FUNCTION(__sanitizer_weak_hook_memcmp)28INTERFACE_WEAK_FUNCTION(__sanitizer_weak_hook_memcmp)
27INTERFACE_WEAK_FUNCTION(__sanitizer_weak_hook_strcmp)29INTERFACE_WEAK_FUNCTION(__sanitizer_weak_hook_strcmp)
...@@ -51,3 +53,9 @@ INTERFACE_WEAK_FUNCTION(__sanitizer_ignore_free_hook)...@@ -51,3 +53,9 @@ INTERFACE_WEAK_FUNCTION(__sanitizer_ignore_free_hook)
51INTERFACE_FUNCTION(__sanitizer_internal_memcpy)53INTERFACE_FUNCTION(__sanitizer_internal_memcpy)
52INTERFACE_FUNCTION(__sanitizer_internal_memmove)54INTERFACE_FUNCTION(__sanitizer_internal_memmove)
53INTERFACE_FUNCTION(__sanitizer_internal_memset)55INTERFACE_FUNCTION(__sanitizer_internal_memset)
56
57#if SANITIZER_WINDOWS
58INTERFACE_FUNCTION(__sanitizer_override_function)
59INTERFACE_FUNCTION(__sanitizer_override_function_by_addr)
60INTERFACE_FUNCTION(__sanitizer_register_weak_function)
61#endif
lib/tsan/sanitizer_common/sanitizer_common_libcdep.cpp+27-1
...@@ -171,7 +171,7 @@ void ReserveShadowMemoryRange(uptr beg, uptr end, const char *name,...@@ -171,7 +171,7 @@ void ReserveShadowMemoryRange(uptr beg, uptr end, const char *name,
171 "ReserveShadowMemoryRange failed while trying to map 0x%zx bytes. "171 "ReserveShadowMemoryRange failed while trying to map 0x%zx bytes. "
172 "Perhaps you're using ulimit -v or ulimit -d\n",172 "Perhaps you're using ulimit -v or ulimit -d\n",
173 size);173 size);
174 Abort();174 Die();
175 }175 }
176 if (madvise_shadow && common_flags()->use_madv_dontdump)176 if (madvise_shadow && common_flags()->use_madv_dontdump)
177 DontDumpShadowMemory(beg, size);177 DontDumpShadowMemory(beg, size);
...@@ -219,6 +219,32 @@ static void StopStackDepotBackgroundThread() {...@@ -219,6 +219,32 @@ static void StopStackDepotBackgroundThread() {
219static void StopStackDepotBackgroundThread() {}219static void StopStackDepotBackgroundThread() {}
220#endif220#endif
221221
222void MemCpyAccessible(void *dest, const void *src, uptr n) {
223 if (TryMemCpy(dest, src, n))
224 return;
225
226 const uptr page_size = GetPageSize();
227 uptr b = reinterpret_cast<uptr>(src);
228 uptr b_up = RoundUpTo(b, page_size);
229
230 uptr e = reinterpret_cast<uptr>(src) + n;
231 uptr e_down = RoundDownTo(e, page_size);
232
233 auto copy_or_zero = [dest, src](uptr beg, uptr end) {
234 const uptr udest = reinterpret_cast<uptr>(dest);
235 const uptr usrc = reinterpret_cast<uptr>(src);
236 void *d = reinterpret_cast<void *>(udest + (beg - usrc));
237 const uptr size = end - beg;
238 if (!TryMemCpy(d, reinterpret_cast<void *>(beg), size))
239 internal_memset(d, 0, size);
240 };
241
242 copy_or_zero(b, b_up);
243 for (uptr p = b_up; p < e_down; p += page_size)
244 copy_or_zero(p, p + page_size);
245 copy_or_zero(e_down, e);
246}
247
222} // namespace __sanitizer248} // namespace __sanitizer
223249
224SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_sandbox_on_notify,250SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_sandbox_on_notify,
lib/tsan/sanitizer_common/sanitizer_common_nolibc.cpp+4-3
...@@ -20,13 +20,14 @@ namespace __sanitizer {...@@ -20,13 +20,14 @@ namespace __sanitizer {
20// The Windows implementations of these functions use the win32 API directly,20// The Windows implementations of these functions use the win32 API directly,
21// bypassing libc.21// bypassing libc.
22#if !SANITIZER_WINDOWS22#if !SANITIZER_WINDOWS
23#if SANITIZER_LINUX23# if SANITIZER_LINUX
24void LogMessageOnPrintf(const char *str) {}24void LogMessageOnPrintf(const char *str) {}
25#endif25void InitTlsSize() {}
26# endif
26void WriteToSyslog(const char *buffer) {}27void WriteToSyslog(const char *buffer) {}
27void Abort() { internal__exit(1); }28void Abort() { internal__exit(1); }
28bool CreateDir(const char *pathname) { return false; }29bool CreateDir(const char *pathname) { return false; }
29#endif // !SANITIZER_WINDOWS30#endif // !SANITIZER_WINDOWS
3031
31#if !SANITIZER_WINDOWS && !SANITIZER_APPLE32#if !SANITIZER_WINDOWS && !SANITIZER_APPLE
32void ListOfModules::init() {}33void ListOfModules::init() {}
lib/tsan/sanitizer_common/sanitizer_common_syscalls.inc+18-15
...@@ -48,6 +48,7 @@...@@ -48,6 +48,7 @@
48#if SANITIZER_LINUX48#if SANITIZER_LINUX
4949
50# include "sanitizer_libc.h"50# include "sanitizer_libc.h"
51# include "sanitizer_platform_limits_posix.h"
5152
52# define PRE_SYSCALL(name) \53# define PRE_SYSCALL(name) \
53 SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_syscall_pre_impl_##name54 SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_syscall_pre_impl_##name
...@@ -2530,18 +2531,19 @@ PRE_SYSCALL(ptrace)(long request, long pid, long addr, long data) {...@@ -2530,18 +2531,19 @@ PRE_SYSCALL(ptrace)(long request, long pid, long addr, long data) {
2530# if !SANITIZER_ANDROID && \2531# if !SANITIZER_ANDROID && \
2531 (defined(__i386) || defined(__x86_64) || defined(__mips64) || \2532 (defined(__i386) || defined(__x86_64) || defined(__mips64) || \
2532 defined(__powerpc64__) || defined(__aarch64__) || defined(__s390__) || \2533 defined(__powerpc64__) || defined(__aarch64__) || defined(__s390__) || \
2533 defined(__loongarch__) || SANITIZER_RISCV64)2534 defined(__loongarch__) || SANITIZER_RISCV64 || defined(__sparc__))
2534 if (data) {2535 long data_arg = ptrace_data_arg(request, addr, data);
2536 if (data_arg) {
2535 if (request == ptrace_setregs) {2537 if (request == ptrace_setregs) {
2536 PRE_READ((void *)data, struct_user_regs_struct_sz);2538 PRE_READ((void *)data_arg, struct_user_regs_struct_sz);
2537 } else if (request == ptrace_setfpregs) {2539 } else if (request == ptrace_setfpregs) {
2538 PRE_READ((void *)data, struct_user_fpregs_struct_sz);2540 PRE_READ((void *)data_arg, struct_user_fpregs_struct_sz);
2539 } else if (request == ptrace_setfpxregs) {2541 } else if (request == ptrace_setfpxregs) {
2540 PRE_READ((void *)data, struct_user_fpxregs_struct_sz);2542 PRE_READ((void *)data_arg, struct_user_fpxregs_struct_sz);
2541 } else if (request == ptrace_setsiginfo) {2543 } else if (request == ptrace_setsiginfo) {
2542 PRE_READ((void *)data, siginfo_t_sz);2544 PRE_READ((void *)data_arg, siginfo_t_sz);
2543 } else if (request == ptrace_setregset) {2545 } else if (request == ptrace_setregset) {
2544 __sanitizer_iovec *iov = (__sanitizer_iovec *)data;2546 __sanitizer_iovec *iov = (__sanitizer_iovec *)data_arg;
2545 PRE_READ(iov->iov_base, iov->iov_len);2547 PRE_READ(iov->iov_base, iov->iov_len);
2546 }2548 }
2547 }2549 }
...@@ -2552,25 +2554,26 @@ POST_SYSCALL(ptrace)(long res, long request, long pid, long addr, long data) {...@@ -2552,25 +2554,26 @@ POST_SYSCALL(ptrace)(long res, long request, long pid, long addr, long data) {
2552# if !SANITIZER_ANDROID && \2554# if !SANITIZER_ANDROID && \
2553 (defined(__i386) || defined(__x86_64) || defined(__mips64) || \2555 (defined(__i386) || defined(__x86_64) || defined(__mips64) || \
2554 defined(__powerpc64__) || defined(__aarch64__) || defined(__s390__) || \2556 defined(__powerpc64__) || defined(__aarch64__) || defined(__s390__) || \
2555 defined(__loongarch__) || SANITIZER_RISCV64)2557 defined(__loongarch__) || SANITIZER_RISCV64 || defined(__sparc__))
2556 if (res >= 0 && data) {2558 long data_arg = ptrace_data_arg(request, addr, data);
2559 if (res >= 0 && data_arg) {
2557 // Note that this is different from the interceptor in2560 // Note that this is different from the interceptor in
2558 // sanitizer_common_interceptors.inc.2561 // sanitizer_common_interceptors.inc.
2559 // PEEK* requests return resulting values through data pointer.2562 // PEEK* requests return resulting values through data pointer.
2560 if (request == ptrace_getregs) {2563 if (request == ptrace_getregs) {
2561 POST_WRITE((void *)data, struct_user_regs_struct_sz);2564 POST_WRITE((void *)data_arg, struct_user_regs_struct_sz);
2562 } else if (request == ptrace_getfpregs) {2565 } else if (request == ptrace_getfpregs) {
2563 POST_WRITE((void *)data, struct_user_fpregs_struct_sz);2566 POST_WRITE((void *)data_arg, struct_user_fpregs_struct_sz);
2564 } else if (request == ptrace_getfpxregs) {2567 } else if (request == ptrace_getfpxregs) {
2565 POST_WRITE((void *)data, struct_user_fpxregs_struct_sz);2568 POST_WRITE((void *)data_arg, struct_user_fpxregs_struct_sz);
2566 } else if (request == ptrace_getsiginfo) {2569 } else if (request == ptrace_getsiginfo) {
2567 POST_WRITE((void *)data, siginfo_t_sz);2570 POST_WRITE((void *)data_arg, siginfo_t_sz);
2568 } else if (request == ptrace_getregset) {2571 } else if (request == ptrace_getregset) {
2569 __sanitizer_iovec *iov = (__sanitizer_iovec *)data;2572 __sanitizer_iovec *iov = (__sanitizer_iovec *)data_arg;
2570 POST_WRITE(iov->iov_base, iov->iov_len);2573 POST_WRITE(iov->iov_base, iov->iov_len);
2571 } else if (request == ptrace_peekdata || request == ptrace_peektext ||2574 } else if (request == ptrace_peekdata || request == ptrace_peektext ||
2572 request == ptrace_peekuser) {2575 request == ptrace_peekuser) {
2573 POST_WRITE((void *)data, sizeof(void *));2576 POST_WRITE((void *)data_arg, sizeof(void *));
2574 }2577 }
2575 }2578 }
2576# endif2579# endif
lib/tsan/sanitizer_common/sanitizer_coverage_win_dll_thunk.cpp deleted-20
...@@ -1,20 +0,0 @@
1//===-- sanitizer_coverage_win_dll_thunk.cpp ------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines a family of thunks that should be statically linked into
10// the DLLs that have instrumentation in order to delegate the calls to the
11// shared runtime that lives in the main binary.
12// See https://github.com/google/sanitizers/issues/209 for the details.
13//===----------------------------------------------------------------------===//
14#ifdef SANITIZER_DLL_THUNK
15#include "sanitizer_win_dll_thunk.h"
16// Sanitizer Coverage interface functions.
17#define INTERFACE_FUNCTION(Name) INTERCEPT_SANITIZER_FUNCTION(Name)
18#define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name)
19#include "sanitizer_coverage_interface.inc"
20#endif // SANITIZER_DLL_THUNK
lib/tsan/sanitizer_common/sanitizer_coverage_win_dynamic_runtime_thunk.cpp deleted-26
...@@ -1,26 +0,0 @@
1//===-- sanitizer_coverage_win_dynamic_runtime_thunk.cpp ------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines things that need to be present in the application modules
10// to interact with Sanitizer Coverage, when it is included in a dll.
11//
12//===----------------------------------------------------------------------===//
13#ifdef SANITIZER_DYNAMIC_RUNTIME_THUNK
14#define SANITIZER_IMPORT_INTERFACE 1
15#include "sanitizer_win_defs.h"
16// Define weak alias for all weak functions imported from sanitizer coverage.
17#define INTERFACE_FUNCTION(Name)
18#define INTERFACE_WEAK_FUNCTION(Name) WIN_WEAK_IMPORT_DEF(Name)
19#include "sanitizer_coverage_interface.inc"
20#endif // SANITIZER_DYNAMIC_RUNTIME_THUNK
21
22namespace __sanitizer {
23// Add one, otherwise unused, external symbol to this object file so that the
24// Visual C++ linker includes it and reads the .drective section.
25void ForceWholeArchiveIncludeForSanCov() {}
26}
lib/tsan/sanitizer_common/sanitizer_coverage_win_weak_interception.cpp deleted-23
...@@ -1,23 +0,0 @@
1//===-- sanitizer_coverage_win_weak_interception.cpp ----------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8// This module should be included in Sanitizer Coverage when it implemented as a
9// shared library on Windows (dll), in order to delegate the calls of weak
10// functions to the implementation in the main executable when a strong
11// definition is provided.
12//===----------------------------------------------------------------------===//
13#ifdef SANITIZER_DYNAMIC
14#include "sanitizer_win_weak_interception.h"
15#include "sanitizer_interface_internal.h"
16#include "sancov_flags.h"
17// Check if strong definitions for weak functions are present in the main
18// executable. If that is the case, override dll functions to point to strong
19// implementations.
20#define INTERFACE_FUNCTION(Name)
21#define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name)
22#include "sanitizer_coverage_interface.inc"
23#endif // SANITIZER_DYNAMIC
lib/tsan/sanitizer_common/sanitizer_deadlock_detector.h+1-1
...@@ -120,7 +120,7 @@ class DeadlockDetectorTLS {...@@ -120,7 +120,7 @@ class DeadlockDetectorTLS {
120 u32 lock;120 u32 lock;
121 u32 stk;121 u32 stk;
122 };122 };
123 LockWithContext all_locks_with_contexts_[64];123 LockWithContext all_locks_with_contexts_[128];
124 uptr n_all_locks_;124 uptr n_all_locks_;
125};125};
126126
lib/tsan/sanitizer_common/sanitizer_dense_map.h+41-29
...@@ -69,24 +69,14 @@ class DenseMapBase {...@@ -69,24 +69,14 @@ class DenseMapBase {
69 setNumTombstones(0);69 setNumTombstones(0);
70 }70 }
7171
72 /// Return true if the specified key is in the map, false otherwise.
73 bool contains(const KeyT &Key) const { return doFind(Key) != nullptr; }
74
72 /// Return 1 if the specified key is in the map, 0 otherwise.75 /// Return 1 if the specified key is in the map, 0 otherwise.
73 size_type count(const KeyT &Key) const {76 size_type count(const KeyT &Key) const { return contains(Key) ? 1 : 0; }
74 const BucketT *TheBucket;
75 return LookupBucketFor(Key, TheBucket) ? 1 : 0;
76 }
7777
78 value_type *find(const KeyT &Key) {78 value_type *find(const KeyT &Key) { return doFind(Key); }
79 BucketT *TheBucket;79 const value_type *find(const KeyT &Key) const { return doFind(Key); }
80 if (LookupBucketFor(Key, TheBucket))
81 return TheBucket;
82 return nullptr;
83 }
84 const value_type *find(const KeyT &Key) const {
85 const BucketT *TheBucket;
86 if (LookupBucketFor(Key, TheBucket))
87 return TheBucket;
88 return nullptr;
89 }
9080
91 /// Alternate version of find() which allows a different, and possibly81 /// Alternate version of find() which allows a different, and possibly
92 /// less expensive, key type.82 /// less expensive, key type.
...@@ -95,25 +85,18 @@ class DenseMapBase {...@@ -95,25 +85,18 @@ class DenseMapBase {
95 /// type used.85 /// type used.
96 template <class LookupKeyT>86 template <class LookupKeyT>
97 value_type *find_as(const LookupKeyT &Key) {87 value_type *find_as(const LookupKeyT &Key) {
98 BucketT *TheBucket;88 return doFind(Key);
99 if (LookupBucketFor(Key, TheBucket))
100 return TheBucket;
101 return nullptr;
102 }89 }
103 template <class LookupKeyT>90 template <class LookupKeyT>
104 const value_type *find_as(const LookupKeyT &Key) const {91 const value_type *find_as(const LookupKeyT &Key) const {
105 const BucketT *TheBucket;92 return doFind(Key);
106 if (LookupBucketFor(Key, TheBucket))
107 return TheBucket;
108 return nullptr;
109 }93 }
11094
111 /// lookup - Return the entry for the specified key, or a default95 /// lookup - Return the entry for the specified key, or a default
112 /// constructed value if no such entry exists.96 /// constructed value if no such entry exists.
113 ValueT lookup(const KeyT &Key) const {97 ValueT lookup(const KeyT &Key) const {
114 const BucketT *TheBucket;98 if (const BucketT *Bucket = doFind(Key))
115 if (LookupBucketFor(Key, TheBucket))99 return Bucket->getSecond();
116 return TheBucket->getSecond();
117 return ValueT();100 return ValueT();
118 }101 }
119102
...@@ -184,8 +167,8 @@ class DenseMapBase {...@@ -184,8 +167,8 @@ class DenseMapBase {
184 }167 }
185168
186 bool erase(const KeyT &Val) {169 bool erase(const KeyT &Val) {
187 BucketT *TheBucket;170 BucketT *TheBucket = doFind(Val);
188 if (!LookupBucketFor(Val, TheBucket))171 if (!TheBucket)
189 return false; // not in map.172 return false; // not in map.
190173
191 TheBucket->getSecond().~ValueT();174 TheBucket->getSecond().~ValueT();
...@@ -449,6 +432,35 @@ class DenseMapBase {...@@ -449,6 +432,35 @@ class DenseMapBase {
449 return TheBucket;432 return TheBucket;
450 }433 }
451434
435 template <typename LookupKeyT>
436 BucketT *doFind(const LookupKeyT &Val) {
437 BucketT *BucketsPtr = getBuckets();
438 const unsigned NumBuckets = getNumBuckets();
439 if (NumBuckets == 0)
440 return nullptr;
441
442 const KeyT EmptyKey = getEmptyKey();
443 unsigned BucketNo = getHashValue(Val) & (NumBuckets - 1);
444 unsigned ProbeAmt = 1;
445 while (true) {
446 BucketT *Bucket = BucketsPtr + BucketNo;
447 if (LIKELY(KeyInfoT::isEqual(Val, Bucket->getFirst())))
448 return Bucket;
449 if (LIKELY(KeyInfoT::isEqual(Bucket->getFirst(), EmptyKey)))
450 return nullptr;
451
452 // Otherwise, it's a hash collision or a tombstone, continue quadratic
453 // probing.
454 BucketNo += ProbeAmt++;
455 BucketNo &= NumBuckets - 1;
456 }
457 }
458
459 template <typename LookupKeyT>
460 const BucketT *doFind(const LookupKeyT &Val) const {
461 return const_cast<DenseMapBase *>(this)->doFind(Val);
462 }
463
452 /// LookupBucketFor - Lookup the appropriate bucket for Val, returning it in464 /// LookupBucketFor - Lookup the appropriate bucket for Val, returning it in
453 /// FoundBucket. If the bucket contains the key and a value, this returns465 /// FoundBucket. If the bucket contains the key and a value, this returns
454 /// true, otherwise it returns a bucket with an empty marker or tombstone and466 /// true, otherwise it returns a bucket with an empty marker or tombstone and
lib/tsan/sanitizer_common/sanitizer_errno.cpp+1
...@@ -23,6 +23,7 @@ namespace __sanitizer {...@@ -23,6 +23,7 @@ namespace __sanitizer {
23COMPILER_CHECK(errno_ENOMEM == ENOMEM);23COMPILER_CHECK(errno_ENOMEM == ENOMEM);
24COMPILER_CHECK(errno_EBUSY == EBUSY);24COMPILER_CHECK(errno_EBUSY == EBUSY);
25COMPILER_CHECK(errno_EINVAL == EINVAL);25COMPILER_CHECK(errno_EINVAL == EINVAL);
26COMPILER_CHECK(errno_ERANGE == ERANGE);
2627
27// EOWNERDEAD is not present in some older platforms.28// EOWNERDEAD is not present in some older platforms.
28#if defined(EOWNERDEAD)29#if defined(EOWNERDEAD)
lib/tsan/sanitizer_common/sanitizer_errno_codes.h+1
...@@ -24,6 +24,7 @@ namespace __sanitizer {...@@ -24,6 +24,7 @@ namespace __sanitizer {
24#define errno_ENOMEM 1224#define errno_ENOMEM 12
25#define errno_EBUSY 1625#define errno_EBUSY 16
26#define errno_EINVAL 2226#define errno_EINVAL 22
27#define errno_ERANGE 34
27#define errno_ENAMETOOLONG 3628#define errno_ENAMETOOLONG 36
28#define errno_ENOSYS 3829#define errno_ENOSYS 38
2930
lib/tsan/sanitizer_common/sanitizer_fuchsia.cpp+5-2
...@@ -94,7 +94,6 @@ void DisableCoreDumperIfNecessary() {}...@@ -94,7 +94,6 @@ void DisableCoreDumperIfNecessary() {}
94void InstallDeadlySignalHandlers(SignalHandlerType handler) {}94void InstallDeadlySignalHandlers(SignalHandlerType handler) {}
95void SetAlternateSignalStack() {}95void SetAlternateSignalStack() {}
96void UnsetAlternateSignalStack() {}96void UnsetAlternateSignalStack() {}
97void InitTlsSize() {}
9897
99bool SignalContext::IsStackOverflow() const { return false; }98bool SignalContext::IsStackOverflow() const { return false; }
100void SignalContext::DumpAllRegisters(void *context) { UNIMPLEMENTED(); }99void SignalContext::DumpAllRegisters(void *context) { UNIMPLEMENTED(); }
...@@ -445,6 +444,11 @@ bool IsAccessibleMemoryRange(uptr beg, uptr size) {...@@ -445,6 +444,11 @@ bool IsAccessibleMemoryRange(uptr beg, uptr size) {
445 return status == ZX_OK;444 return status == ZX_OK;
446}445}
447446
447bool TryMemCpy(void *dest, const void *src, uptr n) {
448 // TODO: implement.
449 return false;
450}
451
448// FIXME implement on this platform.452// FIXME implement on this platform.
449void GetMemoryProfile(fill_profile_f cb, uptr *stats) {}453void GetMemoryProfile(fill_profile_f cb, uptr *stats) {}
450454
...@@ -519,7 +523,6 @@ uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len) {...@@ -519,7 +523,6 @@ uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len) {
519uptr MainThreadStackBase, MainThreadStackSize;523uptr MainThreadStackBase, MainThreadStackSize;
520524
521bool GetRandom(void *buffer, uptr length, bool blocking) {525bool GetRandom(void *buffer, uptr length, bool blocking) {
522 CHECK_LE(length, ZX_CPRNG_DRAW_MAX_LEN);
523 _zx_cprng_draw(buffer, length);526 _zx_cprng_draw(buffer, length);
524 return true;527 return true;
525}528}
lib/tsan/sanitizer_common/sanitizer_getauxval.h+11-12
...@@ -21,22 +21,21 @@...@@ -21,22 +21,21 @@
2121
22#if SANITIZER_LINUX || SANITIZER_FUCHSIA22#if SANITIZER_LINUX || SANITIZER_FUCHSIA
2323
24# if (__GLIBC_PREREQ(2, 16) || (SANITIZER_ANDROID && __ANDROID_API__ >= 21) || \24# if (__GLIBC_PREREQ(2, 16) || SANITIZER_ANDROID || SANITIZER_FUCHSIA) && \
25 SANITIZER_FUCHSIA) && \25 !SANITIZER_GO
26 !SANITIZER_GO26# define SANITIZER_USE_GETAUXVAL 1
27# define SANITIZER_USE_GETAUXVAL 127# else
28# else28# define SANITIZER_USE_GETAUXVAL 0
29# define SANITIZER_USE_GETAUXVAL 029# endif
30# endif30
3131# if SANITIZER_USE_GETAUXVAL
32# if SANITIZER_USE_GETAUXVAL32# include <sys/auxv.h>
33# include <sys/auxv.h>33# else
34# else
35// The weak getauxval definition allows to check for the function at runtime.34// The weak getauxval definition allows to check for the function at runtime.
36// This is useful for Android, when compiled at a lower API level yet running35// This is useful for Android, when compiled at a lower API level yet running
37// on a more recent platform that offers the function.36// on a more recent platform that offers the function.
38extern "C" SANITIZER_WEAK_ATTRIBUTE unsigned long getauxval(unsigned long type);37extern "C" SANITIZER_WEAK_ATTRIBUTE unsigned long getauxval(unsigned long type);
39# endif38# endif
4039
41#elif SANITIZER_NETBSD40#elif SANITIZER_NETBSD
4241
lib/tsan/sanitizer_common/sanitizer_interface_internal.h+10
...@@ -49,6 +49,11 @@ __sanitizer_sandbox_on_notify(__sanitizer_sandbox_arguments *args);...@@ -49,6 +49,11 @@ __sanitizer_sandbox_on_notify(__sanitizer_sandbox_arguments *args);
49SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void49SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
50__sanitizer_report_error_summary(const char *error_summary);50__sanitizer_report_error_summary(const char *error_summary);
5151
52// Returns size of dynamically allocated block. This function can be overridden
53// by the client.
54SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE __sanitizer::uptr
55__sanitizer_get_dtls_size(const void *tls_begin);
56
52SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump();57SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump();
53SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_coverage(58SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_coverage(
54 const __sanitizer::uptr *pcs, const __sanitizer::uptr len);59 const __sanitizer::uptr *pcs, const __sanitizer::uptr len);
...@@ -71,6 +76,11 @@ void __sanitizer_annotate_double_ended_contiguous_container(...@@ -71,6 +76,11 @@ void __sanitizer_annotate_double_ended_contiguous_container(
71 const void *old_container_beg, const void *old_container_end,76 const void *old_container_beg, const void *old_container_end,
72 const void *new_container_beg, const void *new_container_end);77 const void *new_container_beg, const void *new_container_end);
73SANITIZER_INTERFACE_ATTRIBUTE78SANITIZER_INTERFACE_ATTRIBUTE
79void __sanitizer_copy_contiguous_container_annotations(const void *src_begin,
80 const void *src_end,
81 const void *dst_begin,
82 const void *dst_end);
83SANITIZER_INTERFACE_ATTRIBUTE
74int __sanitizer_verify_contiguous_container(const void *beg, const void *mid,84int __sanitizer_verify_contiguous_container(const void *beg, const void *mid,
75 const void *end);85 const void *end);
76SANITIZER_INTERFACE_ATTRIBUTE86SANITIZER_INTERFACE_ATTRIBUTE
lib/tsan/sanitizer_common/sanitizer_internal_defs.h+23-17
...@@ -138,19 +138,25 @@...@@ -138,19 +138,25 @@
138// in a portable way by the language itself.138// in a portable way by the language itself.
139namespace __sanitizer {139namespace __sanitizer {
140140
141#if defined(_WIN64)141#if defined(__UINTPTR_TYPE__)
142# if defined(__arm__) && defined(__linux__)
143// Linux Arm headers redefine __UINTPTR_TYPE__ and disagree with clang/gcc.
144typedef unsigned int uptr;
145typedef int sptr;
146# else
147typedef __UINTPTR_TYPE__ uptr;
148typedef __INTPTR_TYPE__ sptr;
149# endif
150#elif defined(_WIN64)
142// 64-bit Windows uses LLP64 data model.151// 64-bit Windows uses LLP64 data model.
143typedef unsigned long long uptr;152typedef unsigned long long uptr;
144typedef signed long long sptr;153typedef signed long long sptr;
145#else154#elif defined(_WIN32)
146# if (SANITIZER_WORDSIZE == 64) || SANITIZER_APPLE || SANITIZER_WINDOWS
147typedef unsigned long uptr;
148typedef signed long sptr;
149# else
150typedef unsigned int uptr;155typedef unsigned int uptr;
151typedef signed int sptr;156typedef signed int sptr;
152# endif157#else
153#endif // defined(_WIN64)158# error Unsupported compiler, missing __UINTPTR_TYPE__
159#endif // defined(__UINTPTR_TYPE__)
154#if defined(__x86_64__)160#if defined(__x86_64__)
155// Since x32 uses ILP32 data model in 64-bit hardware mode, we must use161// Since x32 uses ILP32 data model in 64-bit hardware mode, we must use
156// 64-bit pointer to unwind stack frame.162// 64-bit pointer to unwind stack frame.
...@@ -194,16 +200,13 @@ typedef u64 OFF64_T;...@@ -194,16 +200,13 @@ typedef u64 OFF64_T;
194#ifdef __SIZE_TYPE__200#ifdef __SIZE_TYPE__
195typedef __SIZE_TYPE__ usize;201typedef __SIZE_TYPE__ usize;
196#else202#else
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;203typedef uptr usize;
206# endif204#endif
205
206#if defined(__s390__) && !defined(__s390x__)
207typedef long ssize;
208#else
209typedef sptr ssize;
207#endif210#endif
208211
209typedef u64 tid_t;212typedef u64 tid_t;
...@@ -466,6 +469,9 @@ using namespace __sanitizer;...@@ -466,6 +469,9 @@ using namespace __sanitizer;
466namespace __msan {469namespace __msan {
467using namespace __sanitizer;470using namespace __sanitizer;
468}471}
472namespace __nsan {
473using namespace __sanitizer;
474}
469namespace __hwasan {475namespace __hwasan {
470using namespace __sanitizer;476using namespace __sanitizer;
471}477}
lib/tsan/sanitizer_common/sanitizer_libignore.cpp+15-13
...@@ -32,7 +32,7 @@ void LibIgnore::AddIgnoredLibrary(const char *name_templ) {...@@ -32,7 +32,7 @@ void LibIgnore::AddIgnoredLibrary(const char *name_templ) {
32 lib->templ = internal_strdup(name_templ);32 lib->templ = internal_strdup(name_templ);
33 lib->name = nullptr;33 lib->name = nullptr;
34 lib->real_name = nullptr;34 lib->real_name = nullptr;
35 lib->loaded = false;35 lib->range_id = kInvalidCodeRangeId;
36}36}
3737
38void LibIgnore::OnLibraryLoaded(const char *name) {38void LibIgnore::OnLibraryLoaded(const char *name) {
...@@ -43,7 +43,7 @@ void LibIgnore::OnLibraryLoaded(const char *name) {...@@ -43,7 +43,7 @@ void LibIgnore::OnLibraryLoaded(const char *name) {
43 buf[0]) {43 buf[0]) {
44 for (uptr i = 0; i < count_; i++) {44 for (uptr i = 0; i < count_; i++) {
45 Lib *lib = &libs_[i];45 Lib *lib = &libs_[i];
46 if (!lib->loaded && (!lib->real_name) &&46 if (!lib->loaded() && (!lib->real_name) &&
47 TemplateMatch(lib->templ, name))47 TemplateMatch(lib->templ, name))
48 lib->real_name = internal_strdup(buf.data());48 lib->real_name = internal_strdup(buf.data());
49 }49 }
...@@ -70,28 +70,31 @@ void LibIgnore::OnLibraryLoaded(const char *name) {...@@ -70,28 +70,31 @@ void LibIgnore::OnLibraryLoaded(const char *name) {
70 Die();70 Die();
71 }71 }
72 loaded = true;72 loaded = true;
73 if (lib->loaded)73 if (lib->loaded())
74 continue;74 continue;
75 VReport(1,75 VReport(1,
76 "Matched called_from_lib suppression '%s' against library"76 "Matched called_from_lib suppression '%s' against library"
77 " '%s'\n",77 " '%s'\n",
78 lib->templ, mod.full_name());78 lib->templ, mod.full_name());
79 lib->loaded = true;
80 lib->name = internal_strdup(mod.full_name());79 lib->name = internal_strdup(mod.full_name());
81 const uptr idx =80 const uptr idx =
82 atomic_load(&ignored_ranges_count_, memory_order_relaxed);81 atomic_load(&ignored_ranges_count_, memory_order_relaxed);
83 CHECK_LT(idx, ARRAY_SIZE(ignored_code_ranges_));82 CHECK_LT(idx, ARRAY_SIZE(ignored_code_ranges_));
84 ignored_code_ranges_[idx].begin = range.beg;83 ignored_code_ranges_[idx].OnLoad(range.beg, range.end);
85 ignored_code_ranges_[idx].end = range.end;84 // Record the index of the ignored range.
85 lib->range_id = idx;
86 atomic_store(&ignored_ranges_count_, idx + 1, memory_order_release);86 atomic_store(&ignored_ranges_count_, idx + 1, memory_order_release);
87 break;87 break;
88 }88 }
89 }89 }
90 if (lib->loaded && !loaded) {90 if (lib->loaded() && !loaded) {
91 Report("%s: library '%s' that was matched against called_from_lib"91 VReport(1,
92 " suppression '%s' is unloaded\n",92 "%s: library '%s' that was matched against called_from_lib"
93 SanitizerToolName, lib->name, lib->templ);93 " suppression '%s' is unloaded\n",
94 Die();94 SanitizerToolName, lib->name, lib->templ);
95 // The library is unloaded so mark the ignored code range as unloaded.
96 ignored_code_ranges_[lib->range_id].OnUnload();
97 lib->range_id = kInvalidCodeRangeId;
95 }98 }
96 }99 }
97100
...@@ -110,8 +113,7 @@ void LibIgnore::OnLibraryLoaded(const char *name) {...@@ -110,8 +113,7 @@ void LibIgnore::OnLibraryLoaded(const char *name) {
110 const uptr idx =113 const uptr idx =
111 atomic_load(&instrumented_ranges_count_, memory_order_relaxed);114 atomic_load(&instrumented_ranges_count_, memory_order_relaxed);
112 CHECK_LT(idx, ARRAY_SIZE(instrumented_code_ranges_));115 CHECK_LT(idx, ARRAY_SIZE(instrumented_code_ranges_));
113 instrumented_code_ranges_[idx].begin = range.beg;116 instrumented_code_ranges_[idx].OnLoad(range.beg, range.end);
114 instrumented_code_ranges_[idx].end = range.end;
115 atomic_store(&instrumented_ranges_count_, idx + 1,117 atomic_store(&instrumented_ranges_count_, idx + 1,
116 memory_order_release);118 memory_order_release);
117 }119 }
lib/tsan/sanitizer_common/sanitizer_libignore.h+23-12
...@@ -49,25 +49,36 @@ class LibIgnore {...@@ -49,25 +49,36 @@ class LibIgnore {
49 bool IsPcInstrumented(uptr pc) const;49 bool IsPcInstrumented(uptr pc) const;
5050
51 private:51 private:
52 static const uptr kMaxIgnoredRanges = 128;
53 static const uptr kMaxInstrumentedRanges = 1024;
54 static const uptr kMaxLibs = 1024;
55 static const uptr kInvalidCodeRangeId = -1;
56
52 struct Lib {57 struct Lib {
53 char *templ;58 char *templ;
54 char *name;59 char *name;
55 char *real_name; // target of symlink60 char *real_name; // target of symlink
56 bool loaded;61 uptr range_id;
62 bool loaded() const { return range_id != kInvalidCodeRangeId; };
57 };63 };
5864
59 struct LibCodeRange {65 struct LibCodeRange {
60 uptr begin;66 bool IsInRange(uptr pc) const {
61 uptr end;67 return (pc >= begin && pc < atomic_load(&end, memory_order_acquire));
62 };68 }
6369
64 inline bool IsInRange(uptr pc, const LibCodeRange &range) const {70 void OnLoad(uptr b, uptr e) {
65 return (pc >= range.begin && pc < range.end);71 begin = b;
66 }72 atomic_store(&end, e, memory_order_release);
73 }
6774
68 static const uptr kMaxIgnoredRanges = 128;75 void OnUnload() { atomic_store(&end, 0, memory_order_release); }
69 static const uptr kMaxInstrumentedRanges = 1024;76
70 static const uptr kMaxLibs = 1024;77 private:
78 uptr begin;
79 // A value of 0 means the associated module was unloaded.
80 atomic_uintptr_t end;
81 };
7182
72 // Hot part:83 // Hot part:
73 atomic_uintptr_t ignored_ranges_count_;84 atomic_uintptr_t ignored_ranges_count_;
...@@ -90,7 +101,7 @@ class LibIgnore {...@@ -90,7 +101,7 @@ class LibIgnore {
90inline bool LibIgnore::IsIgnored(uptr pc, bool *pc_in_ignored_lib) const {101inline bool LibIgnore::IsIgnored(uptr pc, bool *pc_in_ignored_lib) const {
91 const uptr n = atomic_load(&ignored_ranges_count_, memory_order_acquire);102 const uptr n = atomic_load(&ignored_ranges_count_, memory_order_acquire);
92 for (uptr i = 0; i < n; i++) {103 for (uptr i = 0; i < n; i++) {
93 if (IsInRange(pc, ignored_code_ranges_[i])) {104 if (ignored_code_ranges_[i].IsInRange(pc)) {
94 *pc_in_ignored_lib = true;105 *pc_in_ignored_lib = true;
95 return true;106 return true;
96 }107 }
...@@ -104,7 +115,7 @@ inline bool LibIgnore::IsIgnored(uptr pc, bool *pc_in_ignored_lib) const {...@@ -104,7 +115,7 @@ inline bool LibIgnore::IsIgnored(uptr pc, bool *pc_in_ignored_lib) const {
104inline bool LibIgnore::IsPcInstrumented(uptr pc) const {115inline bool LibIgnore::IsPcInstrumented(uptr pc) const {
105 const uptr n = atomic_load(&instrumented_ranges_count_, memory_order_acquire);116 const uptr n = atomic_load(&instrumented_ranges_count_, memory_order_acquire);
106 for (uptr i = 0; i < n; i++) {117 for (uptr i = 0; i < n; i++) {
107 if (IsInRange(pc, instrumented_code_ranges_[i]))118 if (instrumented_code_ranges_[i].IsInRange(pc))
108 return true;119 return true;
109 }120 }
110 return false;121 return false;
lib/tsan/sanitizer_common/sanitizer_linux.cpp+325-71
...@@ -107,7 +107,9 @@ extern struct ps_strings *__ps_strings;...@@ -107,7 +107,9 @@ extern struct ps_strings *__ps_strings;
107# endif // SANITIZER_NETBSD107# endif // SANITIZER_NETBSD
108108
109# if SANITIZER_SOLARIS109# if SANITIZER_SOLARIS
110# include <stddef.h>
110# include <stdlib.h>111# include <stdlib.h>
112# include <sys/frame.h>
111# include <thread.h>113# include <thread.h>
112# define environ _environ114# define environ _environ
113# endif115# endif
...@@ -132,9 +134,10 @@ const int FUTEX_WAKE_PRIVATE = FUTEX_WAKE | FUTEX_PRIVATE_FLAG;...@@ -132,9 +134,10 @@ const int FUTEX_WAKE_PRIVATE = FUTEX_WAKE | FUTEX_PRIVATE_FLAG;
132// Are we using 32-bit or 64-bit Linux syscalls?134// Are we using 32-bit or 64-bit Linux syscalls?
133// x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32135// x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32
134// but it still needs to use 64-bit syscalls.136// but it still needs to use 64-bit syscalls.
135# if SANITIZER_LINUX && (defined(__x86_64__) || defined(__powerpc64__) || \137# if SANITIZER_LINUX && \
136 SANITIZER_WORDSIZE == 64 || \138 (defined(__x86_64__) || defined(__powerpc64__) || \
137 (defined(__mips__) && _MIPS_SIM == _ABIN32))139 SANITIZER_WORDSIZE == 64 || \
140 (defined(__mips__) && defined(_ABIN32) && _MIPS_SIM == _ABIN32))
138# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1141# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1
139# else142# else
140# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0143# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0
...@@ -152,6 +155,8 @@ const int FUTEX_WAKE_PRIVATE = FUTEX_WAKE | FUTEX_PRIVATE_FLAG;...@@ -152,6 +155,8 @@ const int FUTEX_WAKE_PRIVATE = FUTEX_WAKE | FUTEX_PRIVATE_FLAG;
152155
153# if SANITIZER_FREEBSD156# if SANITIZER_FREEBSD
154# define SANITIZER_USE_GETENTROPY 1157# define SANITIZER_USE_GETENTROPY 1
158extern "C" void *__sys_mmap(void *addr, size_t len, int prot, int flags, int fd,
159 off_t offset);
155# endif160# endif
156161
157namespace __sanitizer {162namespace __sanitizer {
...@@ -160,33 +165,56 @@ void SetSigProcMask(__sanitizer_sigset_t *set, __sanitizer_sigset_t *oldset) {...@@ -160,33 +165,56 @@ void SetSigProcMask(__sanitizer_sigset_t *set, __sanitizer_sigset_t *oldset) {
160 CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, set, oldset));165 CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, set, oldset));
161}166}
162167
168# if SANITIZER_LINUX
169// Deletes the specified signal from newset, if it is not present in oldset
170// Equivalently: newset[signum] = newset[signum] & oldset[signum]
171static void KeepUnblocked(__sanitizer_sigset_t &newset,
172 __sanitizer_sigset_t &oldset, int signum) {
173 // FIXME: https://github.com/google/sanitizers/issues/1816
174 if (SANITIZER_ANDROID || !internal_sigismember(&oldset, signum))
175 internal_sigdelset(&newset, signum);
176}
177# endif
178
163// Block asynchronous signals179// Block asynchronous signals
164void BlockSignals(__sanitizer_sigset_t *oldset) {180void BlockSignals(__sanitizer_sigset_t *oldset) {
165 __sanitizer_sigset_t set;181 __sanitizer_sigset_t newset;
166 internal_sigfillset(&set);182 internal_sigfillset(&newset);
167# if SANITIZER_LINUX && !SANITIZER_ANDROID183
184# if SANITIZER_LINUX
185 __sanitizer_sigset_t currentset;
186
187# if !SANITIZER_ANDROID
188 // FIXME: https://github.com/google/sanitizers/issues/1816
189 SetSigProcMask(NULL, &currentset);
190
168 // Glibc uses SIGSETXID signal during setuid call. If this signal is blocked191 // Glibc uses SIGSETXID signal during setuid call. If this signal is blocked
169 // on any thread, setuid call hangs.192 // on any thread, setuid call hangs.
170 // See test/sanitizer_common/TestCases/Linux/setuid.c.193 // See test/sanitizer_common/TestCases/Linux/setuid.c.
171 internal_sigdelset(&set, 33);194 KeepUnblocked(newset, currentset, 33);
172# endif195# endif // !SANITIZER_ANDROID
173# if SANITIZER_LINUX196
174 // Seccomp-BPF-sandboxed processes rely on SIGSYS to handle trapped syscalls.197 // Seccomp-BPF-sandboxed processes rely on SIGSYS to handle trapped syscalls.
175 // If this signal is blocked, such calls cannot be handled and the process may198 // If this signal is blocked, such calls cannot be handled and the process may
176 // hang.199 // hang.
177 internal_sigdelset(&set, 31);200 KeepUnblocked(newset, currentset, 31);
178201
202# if !SANITIZER_ANDROID
179 // Don't block synchronous signals203 // Don't block synchronous signals
180 internal_sigdelset(&set, SIGSEGV);204 // but also don't unblock signals that the user had deliberately blocked.
181 internal_sigdelset(&set, SIGBUS);205 // FIXME: https://github.com/google/sanitizers/issues/1816
182 internal_sigdelset(&set, SIGILL);206 KeepUnblocked(newset, currentset, SIGSEGV);
183 internal_sigdelset(&set, SIGTRAP);207 KeepUnblocked(newset, currentset, SIGBUS);
184 internal_sigdelset(&set, SIGABRT);208 KeepUnblocked(newset, currentset, SIGILL);
185 internal_sigdelset(&set, SIGFPE);209 KeepUnblocked(newset, currentset, SIGTRAP);
186 internal_sigdelset(&set, SIGPIPE);210 KeepUnblocked(newset, currentset, SIGABRT);
187# endif211 KeepUnblocked(newset, currentset, SIGFPE);
212 KeepUnblocked(newset, currentset, SIGPIPE);
213# endif //! SANITIZER_ANDROID
214
215# endif // SANITIZER_LINUX
188216
189 SetSigProcMask(&set, oldset);217 SetSigProcMask(&newset, oldset);
190}218}
191219
192ScopedBlockSignals::ScopedBlockSignals(__sanitizer_sigset_t *copy) {220ScopedBlockSignals::ScopedBlockSignals(__sanitizer_sigset_t *copy) {
...@@ -218,7 +246,9 @@ ScopedBlockSignals::~ScopedBlockSignals() { SetSigProcMask(&saved_, nullptr); }...@@ -218,7 +246,9 @@ ScopedBlockSignals::~ScopedBlockSignals() { SetSigProcMask(&saved_, nullptr); }
218# if !SANITIZER_S390246# if !SANITIZER_S390
219uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd,247uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd,
220 u64 offset) {248 u64 offset) {
221# if SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS249# if SANITIZER_FREEBSD
250 return (uptr)__sys_mmap(addr, length, prot, flags, fd, offset);
251# elif SANITIZER_LINUX_USES_64BIT_SYSCALLS
222 return internal_syscall(SYSCALL(mmap), (uptr)addr, length, prot, flags, fd,252 return internal_syscall(SYSCALL(mmap), (uptr)addr, length, prot, flags, fd,
223 offset);253 offset);
224# else254# else
...@@ -250,6 +280,11 @@ int internal_madvise(uptr addr, uptr length, int advice) {...@@ -250,6 +280,11 @@ int internal_madvise(uptr addr, uptr length, int advice) {
250 return internal_syscall(SYSCALL(madvise), addr, length, advice);280 return internal_syscall(SYSCALL(madvise), addr, length, advice);
251}281}
252282
283# if SANITIZER_FREEBSD
284uptr internal_close_range(fd_t lowfd, fd_t highfd, int flags) {
285 return internal_syscall(SYSCALL(close_range), lowfd, highfd, flags);
286}
287# endif
253uptr internal_close(fd_t fd) { return internal_syscall(SYSCALL(close), fd); }288uptr internal_close(fd_t fd) { return internal_syscall(SYSCALL(close), fd); }
254289
255uptr internal_open(const char *filename, int flags) {290uptr internal_open(const char *filename, int flags) {
...@@ -395,8 +430,9 @@ uptr internal_stat(const char *path, void *buf) {...@@ -395,8 +430,9 @@ uptr internal_stat(const char *path, void *buf) {
395 AT_NO_AUTOMOUNT, STATX_BASIC_STATS, (uptr)&bufx);430 AT_NO_AUTOMOUNT, STATX_BASIC_STATS, (uptr)&bufx);
396 statx_to_stat(&bufx, (struct stat *)buf);431 statx_to_stat(&bufx, (struct stat *)buf);
397 return res;432 return res;
398# elif (SANITIZER_WORDSIZE == 64 || SANITIZER_X32 || \433# elif ( \
399 (defined(__mips__) && _MIPS_SIM == _ABIN32)) && \434 SANITIZER_WORDSIZE == 64 || SANITIZER_X32 || \
435 (defined(__mips__) && defined(_ABIN32) && _MIPS_SIM == _ABIN32)) && \
400 !SANITIZER_SPARC436 !SANITIZER_SPARC
401 return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf,437 return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf,
402 0);438 0);
...@@ -433,8 +469,9 @@ uptr internal_lstat(const char *path, void *buf) {...@@ -433,8 +469,9 @@ uptr internal_lstat(const char *path, void *buf) {
433 STATX_BASIC_STATS, (uptr)&bufx);469 STATX_BASIC_STATS, (uptr)&bufx);
434 statx_to_stat(&bufx, (struct stat *)buf);470 statx_to_stat(&bufx, (struct stat *)buf);
435 return res;471 return res;
436# elif (defined(_LP64) || SANITIZER_X32 || \472# elif ( \
437 (defined(__mips__) && _MIPS_SIM == _ABIN32)) && \473 defined(_LP64) || SANITIZER_X32 || \
474 (defined(__mips__) && defined(_ABIN32) && _MIPS_SIM == _ABIN32)) && \
438 !SANITIZER_SPARC475 !SANITIZER_SPARC
439 return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf,476 return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf,
440 AT_SYMLINK_NOFOLLOW);477 AT_SYMLINK_NOFOLLOW);
...@@ -721,6 +758,11 @@ static void GetArgsAndEnv(char ***argv, char ***envp) {...@@ -721,6 +758,11 @@ static void GetArgsAndEnv(char ***argv, char ***envp) {
721# if !SANITIZER_GO758# if !SANITIZER_GO
722 if (&__libc_stack_end) {759 if (&__libc_stack_end) {
723 uptr *stack_end = (uptr *)__libc_stack_end;760 uptr *stack_end = (uptr *)__libc_stack_end;
761 // Linux/sparc64 needs an adjustment, cf. glibc
762 // sysdeps/sparc/sparc{32,64}/dl-machine.h (DL_STACK_END).
763# if SANITIZER_LINUX && defined(__sparc__)
764 stack_end = &stack_end[16];
765# endif
724 // Normally argc can be obtained from *stack_end, however, on ARM glibc's766 // Normally argc can be obtained from *stack_end, however, on ARM glibc's
725 // _start clobbers it:767 // _start clobbers it:
726 // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/arm/start.S;hb=refs/heads/release/2.31/master#l75768 // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/arm/start.S;hb=refs/heads/release/2.31/master#l75
...@@ -1014,34 +1056,29 @@ bool internal_sigismember(__sanitizer_sigset_t *set, int signum) {...@@ -1014,34 +1056,29 @@ bool internal_sigismember(__sanitizer_sigset_t *set, int signum) {
10141056
1015# if !SANITIZER_NETBSD1057# if !SANITIZER_NETBSD
1016// ThreadLister implementation.1058// ThreadLister implementation.
1017ThreadLister::ThreadLister(pid_t pid) : pid_(pid), buffer_(4096) {1059ThreadLister::ThreadLister(pid_t pid) : buffer_(4096) {
1018 char task_directory_path[80];1060 task_path_.AppendF("/proc/%d/task", pid);
1019 internal_snprintf(task_directory_path, sizeof(task_directory_path),
1020 "/proc/%d/task/", pid);
1021 descriptor_ = internal_open(task_directory_path, O_RDONLY | O_DIRECTORY);
1022 if (internal_iserror(descriptor_)) {
1023 Report("Can't open /proc/%d/task for reading.\n", pid);
1024 }
1025}1061}
10261062
1027ThreadLister::Result ThreadLister::ListThreads(1063ThreadLister::Result ThreadLister::ListThreads(
1028 InternalMmapVector<tid_t> *threads) {1064 InternalMmapVector<tid_t> *threads) {
1029 if (internal_iserror(descriptor_))1065 int descriptor = internal_open(task_path_.data(), O_RDONLY | O_DIRECTORY);
1066 if (internal_iserror(descriptor)) {
1067 Report("Can't open %s for reading.\n", task_path_.data());
1030 return Error;1068 return Error;
1031 internal_lseek(descriptor_, 0, SEEK_SET);1069 }
1070 auto cleanup = at_scope_exit([&] { internal_close(descriptor); });
1032 threads->clear();1071 threads->clear();
10331072
1034 Result result = Ok;1073 Result result = Ok;
1035 for (bool first_read = true;; first_read = false) {1074 for (bool first_read = true;; first_read = false) {
1036 // Resize to max capacity if it was downsized by IsAlive.
1037 buffer_.resize(buffer_.capacity());
1038 CHECK_GE(buffer_.size(), 4096);1075 CHECK_GE(buffer_.size(), 4096);
1039 uptr read = internal_getdents(1076 uptr read = internal_getdents(
1040 descriptor_, (struct linux_dirent *)buffer_.data(), buffer_.size());1077 descriptor, (struct linux_dirent *)buffer_.data(), buffer_.size());
1041 if (!read)1078 if (!read)
1042 return result;1079 return result;
1043 if (internal_iserror(read)) {1080 if (internal_iserror(read)) {
1044 Report("Can't read directory entries from /proc/%d/task.\n", pid_);1081 Report("Can't read directory entries from %s.\n", task_path_.data());
1045 return Error;1082 return Error;
1046 }1083 }
10471084
...@@ -1079,26 +1116,33 @@ ThreadLister::Result ThreadLister::ListThreads(...@@ -1079,26 +1116,33 @@ ThreadLister::Result ThreadLister::ListThreads(
1079 }1116 }
1080}1117}
10811118
1082bool ThreadLister::IsAlive(int tid) {1119const char *ThreadLister::LoadStatus(tid_t tid) {
1120 status_path_.clear();
1121 status_path_.AppendF("%s/%llu/status", task_path_.data(), tid);
1122 auto cleanup = at_scope_exit([&] {
1123 // Resize back to capacity if it is downsized by `ReadFileToVector`.
1124 buffer_.resize(buffer_.capacity());
1125 });
1126 if (!ReadFileToVector(status_path_.data(), &buffer_) || buffer_.empty())
1127 return nullptr;
1128 buffer_.push_back('\0');
1129 return buffer_.data();
1130}
1131
1132bool ThreadLister::IsAlive(tid_t tid) {
1083 // /proc/%d/task/%d/status uses same call to detect alive threads as1133 // /proc/%d/task/%d/status uses same call to detect alive threads as
1084 // proc_task_readdir. See task_state implementation in Linux.1134 // proc_task_readdir. See task_state implementation in Linux.
1085 char path[80];
1086 internal_snprintf(path, sizeof(path), "/proc/%d/task/%d/status", pid_, tid);
1087 if (!ReadFileToVector(path, &buffer_) || buffer_.empty())
1088 return false;
1089 buffer_.push_back(0);
1090 static const char kPrefix[] = "\nPPid:";1135 static const char kPrefix[] = "\nPPid:";
1091 const char *field = internal_strstr(buffer_.data(), kPrefix);1136 const char *status = LoadStatus(tid);
1137 if (!status)
1138 return false;
1139 const char *field = internal_strstr(status, kPrefix);
1092 if (!field)1140 if (!field)
1093 return false;1141 return false;
1094 field += internal_strlen(kPrefix);1142 field += internal_strlen(kPrefix);
1095 return (int)internal_atoll(field) != 0;1143 return (int)internal_atoll(field) != 0;
1096}1144}
10971145
1098ThreadLister::~ThreadLister() {
1099 if (!internal_iserror(descriptor_))
1100 internal_close(descriptor_);
1101}
1102# endif1146# endif
11031147
1104# if SANITIZER_WORDSIZE == 321148# if SANITIZER_WORDSIZE == 32
...@@ -1808,11 +1852,6 @@ int internal_uname(struct utsname *buf) {...@@ -1808,11 +1852,6 @@ int internal_uname(struct utsname *buf) {
1808# endif1852# endif
18091853
1810# if SANITIZER_ANDROID1854# if SANITIZER_ANDROID
1811# if __ANDROID_API__ < 21
1812extern "C" __attribute__((weak)) int dl_iterate_phdr(
1813 int (*)(struct dl_phdr_info *, size_t, void *), void *);
1814# endif
1815
1816static int dl_iterate_phdr_test_cb(struct dl_phdr_info *info, size_t size,1855static int dl_iterate_phdr_test_cb(struct dl_phdr_info *info, size_t size,
1817 void *data) {1856 void *data) {
1818 // Any name starting with "lib" indicates a bug in L where library base names1857 // Any name starting with "lib" indicates a bug in L where library base names
...@@ -1828,9 +1867,7 @@ static int dl_iterate_phdr_test_cb(struct dl_phdr_info *info, size_t size,...@@ -1828,9 +1867,7 @@ static int dl_iterate_phdr_test_cb(struct dl_phdr_info *info, size_t size,
1828static atomic_uint32_t android_api_level;1867static atomic_uint32_t android_api_level;
18291868
1830static AndroidApiLevel AndroidDetectApiLevelStatic() {1869static AndroidApiLevel AndroidDetectApiLevelStatic() {
1831# if __ANDROID_API__ <= 191870# if __ANDROID_API__ <= 22
1832 return ANDROID_KITKAT;
1833# elif __ANDROID_API__ <= 22
1834 return ANDROID_LOLLIPOP_MR1;1871 return ANDROID_LOLLIPOP_MR1;
1835# else1872# else
1836 return ANDROID_POST_LOLLIPOP;1873 return ANDROID_POST_LOLLIPOP;
...@@ -1838,8 +1875,6 @@ static AndroidApiLevel AndroidDetectApiLevelStatic() {...@@ -1838,8 +1875,6 @@ static AndroidApiLevel AndroidDetectApiLevelStatic() {
1838}1875}
18391876
1840static AndroidApiLevel AndroidDetectApiLevel() {1877static AndroidApiLevel AndroidDetectApiLevel() {
1841 if (!&dl_iterate_phdr)
1842 return ANDROID_KITKAT; // K or lower
1843 bool base_name_seen = false;1878 bool base_name_seen = false;
1844 dl_iterate_phdr(dl_iterate_phdr_test_cb, &base_name_seen);1879 dl_iterate_phdr(dl_iterate_phdr_test_cb, &base_name_seen);
1845 if (base_name_seen)1880 if (base_name_seen)
...@@ -2014,6 +2049,18 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {...@@ -2014,6 +2049,18 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
2014 return Unknown;2049 return Unknown;
2015 return esr & ESR_ELx_WNR ? Write : Read;2050 return esr & ESR_ELx_WNR ? Write : Read;
2016# elif defined(__loongarch__)2051# elif defined(__loongarch__)
2052 // In the musl environment, the Linux kernel uapi sigcontext.h is not
2053 // included in signal.h. To avoid missing the SC_ADDRERR_{RD,WR} macros,
2054 // copy them here. The LoongArch Linux kernel uapi is already stable,
2055 // so there's no need to worry about the value changing.
2056# ifndef SC_ADDRERR_RD
2057 // Address error was due to memory load
2058# define SC_ADDRERR_RD (1 << 30)
2059# endif
2060# ifndef SC_ADDRERR_WR
2061 // Address error was due to memory store
2062# define SC_ADDRERR_WR (1 << 31)
2063# endif
2017 u32 flags = ucontext->uc_mcontext.__flags;2064 u32 flags = ucontext->uc_mcontext.__flags;
2018 if (flags & SC_ADDRERR_RD)2065 if (flags & SC_ADDRERR_RD)
2019 return SignalContext::Read;2066 return SignalContext::Read;
...@@ -2154,8 +2201,26 @@ bool SignalContext::IsTrueFaultingAddress() const {...@@ -2154,8 +2201,26 @@ bool SignalContext::IsTrueFaultingAddress() const {
2154UNUSED2201UNUSED
2155static const char *RegNumToRegName(int reg) {2202static const char *RegNumToRegName(int reg) {
2156 switch (reg) {2203 switch (reg) {
2157# if SANITIZER_LINUX2204# if SANITIZER_LINUX && SANITIZER_GLIBC || SANITIZER_NETBSD
2158# if defined(__x86_64__)2205# if defined(__x86_64__)
2206# if SANITIZER_NETBSD
2207# define REG_RAX _REG_RAX
2208# define REG_RBX _REG_RBX
2209# define REG_RCX _REG_RCX
2210# define REG_RDX _REG_RDX
2211# define REG_RDI _REG_RDI
2212# define REG_RSI _REG_RSI
2213# define REG_RBP _REG_RBP
2214# define REG_RSP _REG_RSP
2215# define REG_R8 _REG_R8
2216# define REG_R9 _REG_R9
2217# define REG_R10 _REG_R10
2218# define REG_R11 _REG_R11
2219# define REG_R12 _REG_R12
2220# define REG_R13 _REG_R13
2221# define REG_R14 _REG_R14
2222# define REG_R15 _REG_R15
2223# endif
2159 case REG_RAX:2224 case REG_RAX:
2160 return "rax";2225 return "rax";
2161 case REG_RBX:2226 case REG_RBX:
...@@ -2189,6 +2254,16 @@ static const char *RegNumToRegName(int reg) {...@@ -2189,6 +2254,16 @@ static const char *RegNumToRegName(int reg) {
2189 case REG_R15:2254 case REG_R15:
2190 return "r15";2255 return "r15";
2191# elif defined(__i386__)2256# elif defined(__i386__)
2257# if SANITIZER_NETBSD
2258# define REG_EAX _REG_EAX
2259# define REG_EBX _REG_EBX
2260# define REG_ECX _REG_ECX
2261# define REG_EDX _REG_EDX
2262# define REG_EDI _REG_EDI
2263# define REG_ESI _REG_ESI
2264# define REG_EBP _REG_EBP
2265# define REG_ESP _REG_ESP
2266# endif
2192 case REG_EAX:2267 case REG_EAX:
2193 return "eax";2268 return "eax";
2194 case REG_EBX:2269 case REG_EBX:
...@@ -2205,32 +2280,170 @@ static const char *RegNumToRegName(int reg) {...@@ -2205,32 +2280,170 @@ static const char *RegNumToRegName(int reg) {
2205 return "ebp";2280 return "ebp";
2206 case REG_ESP:2281 case REG_ESP:
2207 return "esp";2282 return "esp";
2283# elif defined(__arm__)
2284# ifdef MAKE_CASE
2285# undef MAKE_CASE
2286# endif
2287# define REG_STR(reg) #reg
2288# define MAKE_CASE(N) \
2289 case REG_R##N: \
2290 return REG_STR(r##N)
2291 MAKE_CASE(0);
2292 MAKE_CASE(1);
2293 MAKE_CASE(2);
2294 MAKE_CASE(3);
2295 MAKE_CASE(4);
2296 MAKE_CASE(5);
2297 MAKE_CASE(6);
2298 MAKE_CASE(7);
2299 MAKE_CASE(8);
2300 MAKE_CASE(9);
2301 MAKE_CASE(10);
2302 MAKE_CASE(11);
2303 MAKE_CASE(12);
2304 case REG_R13:
2305 return "sp";
2306 case REG_R14:
2307 return "lr";
2308 case REG_R15:
2309 return "pc";
2310# elif defined(__aarch64__)
2311# define REG_STR(reg) #reg
2312# define MAKE_CASE(N) \
2313 case N: \
2314 return REG_STR(x##N)
2315 MAKE_CASE(0);
2316 MAKE_CASE(1);
2317 MAKE_CASE(2);
2318 MAKE_CASE(3);
2319 MAKE_CASE(4);
2320 MAKE_CASE(5);
2321 MAKE_CASE(6);
2322 MAKE_CASE(7);
2323 MAKE_CASE(8);
2324 MAKE_CASE(9);
2325 MAKE_CASE(10);
2326 MAKE_CASE(11);
2327 MAKE_CASE(12);
2328 MAKE_CASE(13);
2329 MAKE_CASE(14);
2330 MAKE_CASE(15);
2331 MAKE_CASE(16);
2332 MAKE_CASE(17);
2333 MAKE_CASE(18);
2334 MAKE_CASE(19);
2335 MAKE_CASE(20);
2336 MAKE_CASE(21);
2337 MAKE_CASE(22);
2338 MAKE_CASE(23);
2339 MAKE_CASE(24);
2340 MAKE_CASE(25);
2341 MAKE_CASE(26);
2342 MAKE_CASE(27);
2343 MAKE_CASE(28);
2344 case 29:
2345 return "fp";
2346 case 30:
2347 return "lr";
2348 case 31:
2349 return "sp";
2208# endif2350# endif
2209# endif2351# endif // SANITIZER_LINUX && SANITIZER_GLIBC
2210 default:2352 default:
2211 return NULL;2353 return NULL;
2212 }2354 }
2213 return NULL;2355 return NULL;
2214}2356}
22152357
2216# if SANITIZER_LINUX2358# if ((SANITIZER_LINUX && SANITIZER_GLIBC) || SANITIZER_NETBSD) && \
2359 (defined(__arm__) || defined(__aarch64__))
2360static uptr GetArmRegister(ucontext_t *ctx, int RegNum) {
2361 switch (RegNum) {
2362# if defined(__arm__) && !SANITIZER_NETBSD
2363# ifdef MAKE_CASE
2364# undef MAKE_CASE
2365# endif
2366# define MAKE_CASE(N) \
2367 case REG_R##N: \
2368 return ctx->uc_mcontext.arm_r##N
2369 MAKE_CASE(0);
2370 MAKE_CASE(1);
2371 MAKE_CASE(2);
2372 MAKE_CASE(3);
2373 MAKE_CASE(4);
2374 MAKE_CASE(5);
2375 MAKE_CASE(6);
2376 MAKE_CASE(7);
2377 MAKE_CASE(8);
2378 MAKE_CASE(9);
2379 MAKE_CASE(10);
2380 case REG_R11:
2381 return ctx->uc_mcontext.arm_fp;
2382 case REG_R12:
2383 return ctx->uc_mcontext.arm_ip;
2384 case REG_R13:
2385 return ctx->uc_mcontext.arm_sp;
2386 case REG_R14:
2387 return ctx->uc_mcontext.arm_lr;
2388 case REG_R15:
2389 return ctx->uc_mcontext.arm_pc;
2390# elif defined(__aarch64__)
2391# if SANITIZER_LINUX
2392 case 0 ... 30:
2393 return ctx->uc_mcontext.regs[RegNum];
2394 case 31:
2395 return ctx->uc_mcontext.sp;
2396# elif SANITIZER_NETBSD
2397 case 0 ... 31:
2398 return ctx->uc_mcontext.__gregs[RegNum];
2399# endif
2400# endif
2401 default:
2402 return 0;
2403 }
2404 return 0;
2405}
2406# endif // SANITIZER_LINUX && SANITIZER_GLIBC && (defined(__arm__) ||
2407 // defined(__aarch64__))
2408
2217UNUSED2409UNUSED
2218static void DumpSingleReg(ucontext_t *ctx, int RegNum) {2410static void DumpSingleReg(ucontext_t *ctx, int RegNum) {
2219 const char *RegName = RegNumToRegName(RegNum);2411 const char *RegName = RegNumToRegName(RegNum);
2412# if SANITIZER_LINUX && SANITIZER_GLIBC || SANITIZER_NETBSD
2220# if defined(__x86_64__)2413# if defined(__x86_64__)
2221 Printf("%s%s = 0x%016llx ", internal_strlen(RegName) == 2 ? " " : "",2414 Printf("%s%s = 0x%016llx ", internal_strlen(RegName) == 2 ? " " : "",
2222 RegName, ctx->uc_mcontext.gregs[RegNum]);2415 RegName,
2416# if SANITIZER_LINUX
2417 ctx->uc_mcontext.gregs[RegNum]
2418# elif SANITIZER_NETBSD
2419 ctx->uc_mcontext.__gregs[RegNum]
2420# endif
2421 );
2223# elif defined(__i386__)2422# elif defined(__i386__)
2224 Printf("%s = 0x%08x ", RegName, ctx->uc_mcontext.gregs[RegNum]);2423 Printf("%s = 0x%08x ", RegName,
2424# if SANITIZER_LINUX
2425 ctx->uc_mcontext.gregs[RegNum]
2426# elif SANITIZER_NETBSD
2427 ctx->uc_mcontext.__gregs[RegNum]
2428# endif
2429 );
2430# elif defined(__arm__)
2431 Printf("%s%s = 0x%08zx ", internal_strlen(RegName) == 2 ? " " : "", RegName,
2432 GetArmRegister(ctx, RegNum));
2433# elif defined(__aarch64__)
2434 Printf("%s%s = 0x%016zx ", internal_strlen(RegName) == 2 ? " " : "", RegName,
2435 GetArmRegister(ctx, RegNum));
2225# else2436# else
2226 (void)RegName;2437 (void)RegName;
2227# endif2438# endif
2228}2439# else
2440 (void)RegName;
2229# endif2441# endif
2442}
22302443
2231void SignalContext::DumpAllRegisters(void *context) {2444void SignalContext::DumpAllRegisters(void *context) {
2232 ucontext_t *ucontext = (ucontext_t *)context;2445 ucontext_t *ucontext = (ucontext_t *)context;
2233# if SANITIZER_LINUX2446# if SANITIZER_LINUX && SANITIZER_GLIBC || SANITIZER_NETBSD
2234# if defined(__x86_64__)2447# if defined(__x86_64__)
2235 Report("Register values:\n");2448 Report("Register values:\n");
2236 DumpSingleReg(ucontext, REG_RAX);2449 DumpSingleReg(ucontext, REG_RAX);
...@@ -2269,6 +2482,35 @@ void SignalContext::DumpAllRegisters(void *context) {...@@ -2269,6 +2482,35 @@ void SignalContext::DumpAllRegisters(void *context) {
2269 DumpSingleReg(ucontext, REG_EBP);2482 DumpSingleReg(ucontext, REG_EBP);
2270 DumpSingleReg(ucontext, REG_ESP);2483 DumpSingleReg(ucontext, REG_ESP);
2271 Printf("\n");2484 Printf("\n");
2485# elif defined(__arm__) && !SANITIZER_NETBSD
2486 Report("Register values:\n");
2487 DumpSingleReg(ucontext, REG_R0);
2488 DumpSingleReg(ucontext, REG_R1);
2489 DumpSingleReg(ucontext, REG_R2);
2490 DumpSingleReg(ucontext, REG_R3);
2491 Printf("\n");
2492 DumpSingleReg(ucontext, REG_R4);
2493 DumpSingleReg(ucontext, REG_R5);
2494 DumpSingleReg(ucontext, REG_R6);
2495 DumpSingleReg(ucontext, REG_R7);
2496 Printf("\n");
2497 DumpSingleReg(ucontext, REG_R8);
2498 DumpSingleReg(ucontext, REG_R9);
2499 DumpSingleReg(ucontext, REG_R10);
2500 DumpSingleReg(ucontext, REG_R11);
2501 Printf("\n");
2502 DumpSingleReg(ucontext, REG_R12);
2503 DumpSingleReg(ucontext, REG_R13);
2504 DumpSingleReg(ucontext, REG_R14);
2505 DumpSingleReg(ucontext, REG_R15);
2506 Printf("\n");
2507# elif defined(__aarch64__)
2508 Report("Register values:\n");
2509 for (int i = 0; i <= 31; ++i) {
2510 DumpSingleReg(ucontext, i);
2511 if (i % 4 == 3)
2512 Printf("\n");
2513 }
2272# else2514# else
2273 (void)ucontext;2515 (void)ucontext;
2274# endif2516# endif
...@@ -2310,6 +2552,8 @@ void SignalContext::DumpAllRegisters(void *context) {...@@ -2310,6 +2552,8 @@ void SignalContext::DumpAllRegisters(void *context) {
2310# else2552# else
2311 (void)ucontext;2553 (void)ucontext;
2312# endif2554# endif
2555# else
2556 (void)ucontext;
2313# endif2557# endif
2314 // FIXME: Implement this for other OSes and architectures.2558 // FIXME: Implement this for other OSes and architectures.
2315}2559}
...@@ -2404,7 +2648,19 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {...@@ -2404,7 +2648,19 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
2404# if SANITIZER_SOLARIS2648# if SANITIZER_SOLARIS
2405 ucontext_t *ucontext = (ucontext_t *)context;2649 ucontext_t *ucontext = (ucontext_t *)context;
2406 *pc = ucontext->uc_mcontext.gregs[REG_PC];2650 *pc = ucontext->uc_mcontext.gregs[REG_PC];
2407 *sp = ucontext->uc_mcontext.gregs[REG_O6] + STACK_BIAS;2651 *sp = ucontext->uc_mcontext.gregs[REG_SP] + STACK_BIAS;
2652 // Avoid SEGV when dereferencing sp on stack overflow with non-faulting load.
2653 // This requires a SPARC V9 CPU. Cannot use #ASI_PNF here: only supported
2654 // since clang-19.
2655# if defined(__sparcv9)
2656 asm("ldxa [%[fp]] 0x82, %[bp]"
2657# else
2658 asm("lduwa [%[fp]] 0x82, %[bp]"
2659# endif
2660 : [bp] "=r"(*bp)
2661 : [fp] "r"(&((struct frame *)*sp)->fr_savfp));
2662 if (*bp)
2663 *bp += STACK_BIAS;
2408# else2664# else
2409 // Historical BSDism here.2665 // Historical BSDism here.
2410 struct sigcontext *scontext = (struct sigcontext *)context;2666 struct sigcontext *scontext = (struct sigcontext *)context;
...@@ -2415,8 +2671,8 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {...@@ -2415,8 +2671,8 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
2415 *pc = scontext->si_regs.pc;2671 *pc = scontext->si_regs.pc;
2416 *sp = scontext->si_regs.u_regs[14];2672 *sp = scontext->si_regs.u_regs[14];
2417# endif2673# endif
2418# endif
2419 *bp = (uptr)((uhwptr *)*sp)[14] + STACK_BIAS;2674 *bp = (uptr)((uhwptr *)*sp)[14] + STACK_BIAS;
2675# endif
2420# elif defined(__mips__)2676# elif defined(__mips__)
2421 ucontext_t *ucontext = (ucontext_t *)context;2677 ucontext_t *ucontext = (ucontext_t *)context;
2422 *pc = ucontext->uc_mcontext.pc;2678 *pc = ucontext->uc_mcontext.pc;
...@@ -2459,9 +2715,7 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {...@@ -2459,9 +2715,7 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
24592715
2460void SignalContext::InitPcSpBp() { GetPcSpBp(context, &pc, &sp, &bp); }2716void SignalContext::InitPcSpBp() { GetPcSpBp(context, &pc, &sp, &bp); }
24612717
2462void InitializePlatformEarly() {2718void InitializePlatformEarly() { InitTlsSize(); }
2463 // Do nothing.
2464}
24652719
2466void CheckASLR() {2720void CheckASLR() {
2467# if SANITIZER_NETBSD2721# if SANITIZER_NETBSD
lib/tsan/sanitizer_common/sanitizer_linux.h+4-4
...@@ -97,19 +97,19 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg);...@@ -97,19 +97,19 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg);
97class ThreadLister {97class ThreadLister {
98 public:98 public:
99 explicit ThreadLister(pid_t pid);99 explicit ThreadLister(pid_t pid);
100 ~ThreadLister();
101 enum Result {100 enum Result {
102 Error,101 Error,
103 Incomplete,102 Incomplete,
104 Ok,103 Ok,
105 };104 };
106 Result ListThreads(InternalMmapVector<tid_t> *threads);105 Result ListThreads(InternalMmapVector<tid_t> *threads);
106 const char *LoadStatus(tid_t tid);
107107
108 private:108 private:
109 bool IsAlive(int tid);109 bool IsAlive(tid_t tid);
110110
111 pid_t pid_;111 InternalScopedString task_path_;
112 int descriptor_ = -1;112 InternalScopedString status_path_;
113 InternalMmapVector<char> buffer_;113 InternalMmapVector<char> buffer_;
114};114};
115115
lib/tsan/sanitizer_common/sanitizer_linux_libcdep.cpp+171-129
...@@ -40,6 +40,10 @@...@@ -40,6 +40,10 @@
40# include <sys/resource.h>40# include <sys/resource.h>
41# include <syslog.h>41# include <syslog.h>
4242
43# if SANITIZER_GLIBC
44# include <gnu/libc-version.h>
45# endif
46
43# if !defined(ElfW)47# if !defined(ElfW)
44# define ElfW(type) Elf_##type48# define ElfW(type) Elf_##type
45# endif49# endif
...@@ -53,7 +57,7 @@...@@ -53,7 +57,7 @@
53// that, it was never implemented. So just define it to zero.57// that, it was never implemented. So just define it to zero.
54# undef MAP_NORESERVE58# undef MAP_NORESERVE
55# define MAP_NORESERVE 059# define MAP_NORESERVE 0
56extern const Elf_Auxinfo *__elf_aux_vector;60extern const Elf_Auxinfo *__elf_aux_vector __attribute__((weak));
57extern "C" int __sys_sigaction(int signum, const struct sigaction *act,61extern "C" int __sys_sigaction(int signum, const struct sigaction *act,
58 struct sigaction *oldact);62 struct sigaction *oldact);
59# endif63# endif
...@@ -196,27 +200,6 @@ bool SetEnv(const char *name, const char *value) {...@@ -196,27 +200,6 @@ bool SetEnv(const char *name, const char *value) {
196}200}
197# endif201# endif
198202
199__attribute__((unused)) static bool GetLibcVersion(int *major, int *minor,
200 int *patch) {
201# ifdef _CS_GNU_LIBC_VERSION
202 char buf[64];
203 uptr len = confstr(_CS_GNU_LIBC_VERSION, buf, sizeof(buf));
204 if (len >= sizeof(buf))
205 return false;
206 buf[len] = 0;
207 static const char kGLibC[] = "glibc ";
208 if (internal_strncmp(buf, kGLibC, sizeof(kGLibC) - 1) != 0)
209 return false;
210 const char *p = buf + sizeof(kGLibC) - 1;
211 *major = internal_simple_strtoll(p, &p, 10);
212 *minor = (*p == '.') ? internal_simple_strtoll(p + 1, &p, 10) : 0;
213 *patch = (*p == '.') ? internal_simple_strtoll(p + 1, &p, 10) : 0;
214 return true;
215# else
216 return false;
217# endif
218}
219
220// True if we can use dlpi_tls_data. glibc before 2.25 may leave NULL (BZ203// True if we can use dlpi_tls_data. glibc before 2.25 may leave NULL (BZ
221// #19826) so dlpi_tls_data cannot be used.204// #19826) so dlpi_tls_data cannot be used.
222//205//
...@@ -226,112 +209,166 @@ __attribute__((unused)) static bool GetLibcVersion(int *major, int *minor,...@@ -226,112 +209,166 @@ __attribute__((unused)) static bool GetLibcVersion(int *major, int *minor,
226__attribute__((unused)) static int g_use_dlpi_tls_data;209__attribute__((unused)) static int g_use_dlpi_tls_data;
227210
228# if SANITIZER_GLIBC && !SANITIZER_GO211# if SANITIZER_GLIBC && !SANITIZER_GO
229__attribute__((unused)) static size_t g_tls_size;212static void GetGLibcVersion(int *major, int *minor, int *patch) {
230void InitTlsSize() {213 const char *p = gnu_get_libc_version();
231 int major, minor, patch;214 *major = internal_simple_strtoll(p, &p, 10);
232 g_use_dlpi_tls_data =215 // Caller does not expect anything else.
233 GetLibcVersion(&major, &minor, &patch) && major == 2 && minor >= 25;216 CHECK_EQ(*major, 2);
234217 *minor = (*p == '.') ? internal_simple_strtoll(p + 1, &p, 10) : 0;
235# if defined(__aarch64__) || defined(__x86_64__) || \218 *patch = (*p == '.') ? internal_simple_strtoll(p + 1, &p, 10) : 0;
236 defined(__powerpc64__) || defined(__loongarch__)
237 void *get_tls_static_info = dlsym(RTLD_NEXT, "_dl_get_tls_static_info");
238 size_t tls_align;
239 ((void (*)(size_t *, size_t *))get_tls_static_info)(&g_tls_size, &tls_align);
240# endif
241}219}
242# else
243void InitTlsSize() {}
244# endif // SANITIZER_GLIBC && !SANITIZER_GO
245
246// On glibc x86_64, ThreadDescriptorSize() needs to be precise due to the usage
247// of g_tls_size. On other targets, ThreadDescriptorSize() is only used by lsan
248// to get the pointer to thread-specific data keys in the thread control block.
249# if (SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_SOLARIS) && \
250 !SANITIZER_ANDROID && !SANITIZER_GO
251// sizeof(struct pthread) from glibc.
252static atomic_uintptr_t thread_descriptor_size;
253220
254static uptr ThreadDescriptorSizeFallback() {221static uptr ThreadDescriptorSizeFallback() {
255 uptr val = 0;222# if defined(__x86_64__) || defined(__i386__) || defined(__arm__) || \
256# if defined(__x86_64__) || defined(__i386__) || defined(__arm__)223 SANITIZER_RISCV64
257 int major;224 int major;
258 int minor;225 int minor;
259 int patch;226 int patch;
260 if (GetLibcVersion(&major, &minor, &patch) && major == 2) {227 GetGLibcVersion(&major, &minor, &patch);
261 /* sizeof(struct pthread) values from various glibc versions. */228# endif
262 if (SANITIZER_X32)229
263 val = 1728; // Assume only one particular version for x32.230# if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
264 // For ARM sizeof(struct pthread) changed in Glibc 2.23.231 /* sizeof(struct pthread) values from various glibc versions. */
265 else if (SANITIZER_ARM)232 if (SANITIZER_X32)
266 val = minor <= 22 ? 1120 : 1216;233 return 1728; // Assume only one particular version for x32.
267 else if (minor <= 3)234 // For ARM sizeof(struct pthread) changed in Glibc 2.23.
268 val = FIRST_32_SECOND_64(1104, 1696);235 if (SANITIZER_ARM)
269 else if (minor == 4)236 return minor <= 22 ? 1120 : 1216;
270 val = FIRST_32_SECOND_64(1120, 1728);237 if (minor <= 3)
271 else if (minor == 5)238 return FIRST_32_SECOND_64(1104, 1696);
272 val = FIRST_32_SECOND_64(1136, 1728);239 if (minor == 4)
273 else if (minor <= 9)240 return FIRST_32_SECOND_64(1120, 1728);
274 val = FIRST_32_SECOND_64(1136, 1712);241 if (minor == 5)
275 else if (minor == 10)242 return FIRST_32_SECOND_64(1136, 1728);
276 val = FIRST_32_SECOND_64(1168, 1776);243 if (minor <= 9)
277 else if (minor == 11 || (minor == 12 && patch == 1))244 return FIRST_32_SECOND_64(1136, 1712);
278 val = FIRST_32_SECOND_64(1168, 2288);245 if (minor == 10)
279 else if (minor <= 14)246 return FIRST_32_SECOND_64(1168, 1776);
280 val = FIRST_32_SECOND_64(1168, 2304);247 if (minor == 11 || (minor == 12 && patch == 1))
281 else if (minor < 32) // Unknown version248 return FIRST_32_SECOND_64(1168, 2288);
282 val = FIRST_32_SECOND_64(1216, 2304);249 if (minor <= 14)
283 else // minor == 32250 return FIRST_32_SECOND_64(1168, 2304);
284 val = FIRST_32_SECOND_64(1344, 2496);251 if (minor < 32) // Unknown version
285 }252 return FIRST_32_SECOND_64(1216, 2304);
286# elif defined(__s390__) || defined(__sparc__)253 // minor == 32
254 return FIRST_32_SECOND_64(1344, 2496);
255# endif
256
257# if SANITIZER_RISCV64
258 // TODO: consider adding an optional runtime check for an unknown (untested)
259 // glibc version
260 if (minor <= 28) // WARNING: the highest tested version is 2.29
261 return 1772; // no guarantees for this one
262 if (minor <= 31)
263 return 1772; // tested against glibc 2.29, 2.31
264 return 1936; // tested against glibc 2.32
265# endif
266
267# if defined(__s390__) || defined(__sparc__)
287 // The size of a prefix of TCB including pthread::{specific_1stblock,specific}268 // The size of a prefix of TCB including pthread::{specific_1stblock,specific}
288 // suffices. Just return offsetof(struct pthread, specific_used), which hasn't269 // suffices. Just return offsetof(struct pthread, specific_used), which hasn't
289 // changed since 2007-05. Technically this applies to i386/x86_64 as well but270 // changed since 2007-05. Technically this applies to i386/x86_64 as well but
290 // we call _dl_get_tls_static_info and need the precise size of struct271 // we call _dl_get_tls_static_info and need the precise size of struct
291 // pthread.272 // pthread.
292 return FIRST_32_SECOND_64(524, 1552);273 return FIRST_32_SECOND_64(524, 1552);
293# elif defined(__mips__)274# endif
275
276# if defined(__mips__)
294 // TODO(sagarthakur): add more values as per different glibc versions.277 // TODO(sagarthakur): add more values as per different glibc versions.
295 val = FIRST_32_SECOND_64(1152, 1776);278 return FIRST_32_SECOND_64(1152, 1776);
296# elif SANITIZER_LOONGARCH64279# endif
297 val = 1856; // from glibc 2.36280
298# elif SANITIZER_RISCV64281# if SANITIZER_LOONGARCH64
299 int major;282 return 1856; // from glibc 2.36
300 int minor;283# endif
301 int patch;
302 if (GetLibcVersion(&major, &minor, &patch) && major == 2) {
303 // TODO: consider adding an optional runtime check for an unknown (untested)
304 // glibc version
305 if (minor <= 28) // WARNING: the highest tested version is 2.29
306 val = 1772; // no guarantees for this one
307 else if (minor <= 31)
308 val = 1772; // tested against glibc 2.29, 2.31
309 else
310 val = 1936; // tested against glibc 2.32
311 }
312284
313# elif defined(__aarch64__)285# if defined(__aarch64__)
314 // The sizeof (struct pthread) is the same from GLIBC 2.17 to 2.22.286 // The sizeof (struct pthread) is the same from GLIBC 2.17 to 2.22.
315 val = 1776;287 return 1776;
316# elif defined(__powerpc64__)288# endif
317 val = 1776; // from glibc.ppc64le 2.20-8.fc21289
290# if defined(__powerpc64__)
291 return 1776; // from glibc.ppc64le 2.20-8.fc21
318# endif292# endif
319 return val;
320}293}
294# endif // SANITIZER_GLIBC && !SANITIZER_GO
295
296# if SANITIZER_FREEBSD && !SANITIZER_GO
297// FIXME: Implementation is very GLIBC specific, but it's used by FreeBSD.
298static uptr ThreadDescriptorSizeFallback() {
299# if defined(__s390__) || defined(__sparc__)
300 // The size of a prefix of TCB including pthread::{specific_1stblock,specific}
301 // suffices. Just return offsetof(struct pthread, specific_used), which hasn't
302 // changed since 2007-05. Technically this applies to i386/x86_64 as well but
303 // we call _dl_get_tls_static_info and need the precise size of struct
304 // pthread.
305 return FIRST_32_SECOND_64(524, 1552);
306# endif
321307
322uptr ThreadDescriptorSize() {308# if defined(__mips__)
323 uptr val = atomic_load_relaxed(&thread_descriptor_size);309 // TODO(sagarthakur): add more values as per different glibc versions.
324 if (val)310 return FIRST_32_SECOND_64(1152, 1776);
325 return val;311# endif
326 // _thread_db_sizeof_pthread is a GLIBC_PRIVATE symbol that is exported in312
327 // glibc 2.34 and later.313# if SANITIZER_LOONGARCH64
328 if (unsigned *psizeof = static_cast<unsigned *>(314 return 1856; // from glibc 2.36
329 dlsym(RTLD_DEFAULT, "_thread_db_sizeof_pthread")))315# endif
330 val = *psizeof;316
331 if (!val)317# if defined(__aarch64__)
332 val = ThreadDescriptorSizeFallback();318 // The sizeof (struct pthread) is the same from GLIBC 2.17 to 2.22.
333 atomic_store_relaxed(&thread_descriptor_size, val);319 return 1776;
334 return val;320# endif
321
322# if defined(__powerpc64__)
323 return 1776; // from glibc.ppc64le 2.20-8.fc21
324# endif
325
326 return 0;
327}
328# endif // SANITIZER_FREEBSD && !SANITIZER_GO
329
330# if (SANITIZER_FREEBSD || SANITIZER_GLIBC) && !SANITIZER_GO
331// On glibc x86_64, ThreadDescriptorSize() needs to be precise due to the usage
332// of g_tls_size. On other targets, ThreadDescriptorSize() is only used by lsan
333// to get the pointer to thread-specific data keys in the thread control block.
334// sizeof(struct pthread) from glibc.
335static uptr thread_descriptor_size;
336
337uptr ThreadDescriptorSize() { return thread_descriptor_size; }
338
339# if SANITIZER_GLIBC
340__attribute__((unused)) static size_t g_tls_size;
341# endif
342
343void InitTlsSize() {
344# if SANITIZER_GLIBC
345 int major, minor, patch;
346 GetGLibcVersion(&major, &minor, &patch);
347 g_use_dlpi_tls_data = major == 2 && minor >= 25;
348
349 if (major == 2 && minor >= 34) {
350 // _thread_db_sizeof_pthread is a GLIBC_PRIVATE symbol that is exported in
351 // glibc 2.34 and later.
352 if (unsigned *psizeof = static_cast<unsigned *>(
353 dlsym(RTLD_DEFAULT, "_thread_db_sizeof_pthread"))) {
354 thread_descriptor_size = *psizeof;
355 }
356 }
357
358# if defined(__aarch64__) || defined(__x86_64__) || \
359 defined(__powerpc64__) || defined(__loongarch__)
360 auto *get_tls_static_info = (void (*)(size_t *, size_t *))dlsym(
361 RTLD_DEFAULT, "_dl_get_tls_static_info");
362 size_t tls_align;
363 // Can be null if static link.
364 if (get_tls_static_info)
365 get_tls_static_info(&g_tls_size, &tls_align);
366# endif
367
368# endif // SANITIZER_GLIBC
369
370 if (!thread_descriptor_size)
371 thread_descriptor_size = ThreadDescriptorSizeFallback();
335}372}
336373
337# if defined(__mips__) || defined(__powerpc64__) || SANITIZER_RISCV64 || \374# if defined(__mips__) || defined(__powerpc64__) || SANITIZER_RISCV64 || \
...@@ -354,7 +391,13 @@ static uptr TlsPreTcbSize() {...@@ -354,7 +391,13 @@ static uptr TlsPreTcbSize() {
354 return kTlsPreTcbSize;391 return kTlsPreTcbSize;
355}392}
356# endif393# endif
394# else // (SANITIZER_FREEBSD || SANITIZER_GLIBC) && !SANITIZER_GO
395void InitTlsSize() {}
396uptr ThreadDescriptorSize() { return 0; }
397# endif // (SANITIZER_FREEBSD || SANITIZER_GLIBC) && !SANITIZER_GO
357398
399# if (SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_SOLARIS) && \
400 !SANITIZER_ANDROID && !SANITIZER_GO
358namespace {401namespace {
359struct TlsBlock {402struct TlsBlock {
360 uptr begin, end, align;403 uptr begin, end, align;
...@@ -626,25 +669,32 @@ uptr GetTlsSize() {...@@ -626,25 +669,32 @@ uptr GetTlsSize() {
626}669}
627# endif670# endif
628671
629void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,672void GetThreadStackAndTls(bool main, uptr *stk_begin, uptr *stk_end,
630 uptr *tls_addr, uptr *tls_size) {673 uptr *tls_begin, uptr *tls_end) {
631# if SANITIZER_GO674# if SANITIZER_GO
632 // Stub implementation for Go.675 // Stub implementation for Go.
633 *stk_addr = *stk_size = *tls_addr = *tls_size = 0;676 *stk_begin = 0;
677 *stk_end = 0;
678 *tls_begin = 0;
679 *tls_end = 0;
634# else680# else
635 GetTls(tls_addr, tls_size);681 uptr tls_addr = 0;
682 uptr tls_size = 0;
683 GetTls(&tls_addr, &tls_size);
684 *tls_begin = tls_addr;
685 *tls_end = tls_addr + tls_size;
636686
637 uptr stack_top, stack_bottom;687 uptr stack_top, stack_bottom;
638 GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);688 GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
639 *stk_addr = stack_bottom;689 *stk_begin = stack_bottom;
640 *stk_size = stack_top - stack_bottom;690 *stk_end = stack_top;
641691
642 if (!main) {692 if (!main) {
643 // If stack and tls intersect, make them non-intersecting.693 // If stack and tls intersect, make them non-intersecting.
644 if (*tls_addr > *stk_addr && *tls_addr < *stk_addr + *stk_size) {694 if (*tls_begin > *stk_begin && *tls_begin < *stk_end) {
645 if (*stk_addr + *stk_size < *tls_addr + *tls_size)695 if (*stk_end < *tls_end)
646 *tls_size = *stk_addr + *stk_size - *tls_addr;696 *tls_end = *stk_end;
647 *stk_size = *tls_addr - *stk_addr;697 *stk_end = *tls_begin;
648 }698 }
649 }699 }
650# endif700# endif
...@@ -723,11 +773,6 @@ static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) {...@@ -723,11 +773,6 @@ static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) {
723 return 0;773 return 0;
724}774}
725775
726# if SANITIZER_ANDROID && __ANDROID_API__ < 21
727extern "C" __attribute__((weak)) int dl_iterate_phdr(
728 int (*)(struct dl_phdr_info *, size_t, void *), void *);
729# endif
730
731static bool requiresProcmaps() {776static bool requiresProcmaps() {
732# if SANITIZER_ANDROID && __ANDROID_API__ <= 22777# if SANITIZER_ANDROID && __ANDROID_API__ <= 22
733 // Fall back to /proc/maps if dl_iterate_phdr is unavailable or broken.778 // Fall back to /proc/maps if dl_iterate_phdr is unavailable or broken.
...@@ -890,11 +935,8 @@ extern "C" SANITIZER_WEAK_ATTRIBUTE int __android_log_write(int prio,...@@ -890,11 +935,8 @@ extern "C" SANITIZER_WEAK_ATTRIBUTE int __android_log_write(int prio,
890void WriteOneLineToSyslog(const char *s) {935void WriteOneLineToSyslog(const char *s) {
891 if (&async_safe_write_log) {936 if (&async_safe_write_log) {
892 async_safe_write_log(SANITIZER_ANDROID_LOG_INFO, GetProcessName(), s);937 async_safe_write_log(SANITIZER_ANDROID_LOG_INFO, GetProcessName(), s);
893 } else if (AndroidGetApiLevel() > ANDROID_KITKAT) {
894 syslog(LOG_INFO, "%s", s);
895 } else {938 } else {
896 CHECK(&__android_log_write);939 syslog(LOG_INFO, "%s", s);
897 __android_log_write(SANITIZER_ANDROID_LOG_INFO, nullptr, s);
898 }940 }
899}941}
900942
lib/tsan/sanitizer_common/sanitizer_mac.cpp+36-28
...@@ -45,7 +45,7 @@ extern char **environ;...@@ -45,7 +45,7 @@ extern char **environ;
45# define SANITIZER_OS_TRACE 045# define SANITIZER_OS_TRACE 0
46# endif46# endif
4747
48// import new crash reporting api48// Integrate with CrashReporter library if available
49# if defined(__has_include) && __has_include(<CrashReporterClient.h>)49# if defined(__has_include) && __has_include(<CrashReporterClient.h>)
50# define HAVE_CRASHREPORTERCLIENT_H 150# define HAVE_CRASHREPORTERCLIENT_H 1
51# include <CrashReporterClient.h>51# include <CrashReporterClient.h>
...@@ -545,9 +545,6 @@ uptr GetTlsSize() {...@@ -545,9 +545,6 @@ uptr GetTlsSize() {
545 return 0;545 return 0;
546}546}
547547
548void InitTlsSize() {
549}
550
551uptr TlsBaseAddr() {548uptr TlsBaseAddr() {
552 uptr segbase = 0;549 uptr segbase = 0;
553#if defined(__x86_64__)550#if defined(__x86_64__)
...@@ -572,21 +569,18 @@ uptr TlsSize() {...@@ -572,21 +569,18 @@ uptr TlsSize() {
572#endif569#endif
573}570}
574571
575void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,572void GetThreadStackAndTls(bool main, uptr *stk_begin, uptr *stk_end,
576 uptr *tls_addr, uptr *tls_size) {573 uptr *tls_begin, uptr *tls_end) {
577#if !SANITIZER_GO574# if !SANITIZER_GO
578 uptr stack_top, stack_bottom;575 GetThreadStackTopAndBottom(main, stk_end, stk_begin);
579 GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);576 *tls_begin = TlsBaseAddr();
580 *stk_addr = stack_bottom;577 *tls_end = *tls_begin + TlsSize();
581 *stk_size = stack_top - stack_bottom;578# else
582 *tls_addr = TlsBaseAddr();579 *stk_begin = 0;
583 *tls_size = TlsSize();580 *stk_end = 0;
584#else581 *tls_begin = 0;
585 *stk_addr = 0;582 *tls_end = 0;
586 *stk_size = 0;583# endif
587 *tls_addr = 0;
588 *tls_size = 0;
589#endif
590}584}
591585
592void ListOfModules::init() {586void ListOfModules::init() {
...@@ -788,7 +782,11 @@ void WriteOneLineToSyslog(const char *s) {...@@ -788,7 +782,11 @@ void WriteOneLineToSyslog(const char *s) {
788 if (GetMacosAlignedVersion() >= MacosVersion(10, 12)) {782 if (GetMacosAlignedVersion() >= MacosVersion(10, 12)) {
789 os_log_error(OS_LOG_DEFAULT, "%{public}s", s);783 os_log_error(OS_LOG_DEFAULT, "%{public}s", s);
790 } else {784 } else {
785#pragma clang diagnostic push
786// as_log is deprecated.
787#pragma clang diagnostic ignored "-Wdeprecated-declarations"
791 asl_log(nullptr, nullptr, ASL_LEVEL_ERR, "%s", s);788 asl_log(nullptr, nullptr, ASL_LEVEL_ERR, "%s", s);
789#pragma clang diagnostic pop
792 }790 }
793#endif791#endif
794}792}
...@@ -798,8 +796,13 @@ static char crashreporter_info_buff[__sanitizer::kErrorMessageBufferSize] = {};...@@ -798,8 +796,13 @@ static char crashreporter_info_buff[__sanitizer::kErrorMessageBufferSize] = {};
798static Mutex crashreporter_info_mutex;796static Mutex crashreporter_info_mutex;
799797
800extern "C" {798extern "C" {
801// Integrate with crash reporter libraries.799
802#if HAVE_CRASHREPORTERCLIENT_H800#if HAVE_CRASHREPORTERCLIENT_H
801// Available in CRASHREPORTER_ANNOTATIONS_VERSION 5+
802# ifdef CRASHREPORTER_ANNOTATIONS_INITIALIZER
803CRASHREPORTER_ANNOTATIONS_INITIALIZER()
804# else
805// Support for older CrashRerporter annotiations
803CRASH_REPORTER_CLIENT_HIDDEN806CRASH_REPORTER_CLIENT_HIDDEN
804struct crashreporter_annotations_t gCRAnnotations807struct crashreporter_annotations_t gCRAnnotations
805 __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION))) = {808 __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION))) = {
...@@ -810,17 +813,17 @@ struct crashreporter_annotations_t gCRAnnotations...@@ -810,17 +813,17 @@ struct crashreporter_annotations_t gCRAnnotations
810 0,813 0,
811 0,814 0,
812 0,815 0,
813#if CRASHREPORTER_ANNOTATIONS_VERSION > 4816# if CRASHREPORTER_ANNOTATIONS_VERSION > 4
814 0,817 0,
815#endif818# endif
816};819};
817820# endif
818#else821# else
819// fall back to old crashreporter api822// Revert to previous crash reporter API if client header is not available
820static const char *__crashreporter_info__ __attribute__((__used__)) =823static const char *__crashreporter_info__ __attribute__((__used__)) =
821 &crashreporter_info_buff[0];824 &crashreporter_info_buff[0];
822asm(".desc ___crashreporter_info__, 0x10");825asm(".desc ___crashreporter_info__, 0x10");
823#endif826#endif // HAVE_CRASHREPORTERCLIENT_H
824827
825} // extern "C"828} // extern "C"
826829
...@@ -843,6 +846,9 @@ void LogFullErrorReport(const char *buffer) {...@@ -843,6 +846,9 @@ void LogFullErrorReport(const char *buffer) {
843#if !SANITIZER_GO846#if !SANITIZER_GO
844 // Log with os_trace. This will make it into the crash log.847 // Log with os_trace. This will make it into the crash log.
845#if SANITIZER_OS_TRACE848#if SANITIZER_OS_TRACE
849#pragma clang diagnostic push
850// os_trace is deprecated.
851#pragma clang diagnostic ignored "-Wdeprecated-declarations"
846 if (GetMacosAlignedVersion() >= MacosVersion(10, 10)) {852 if (GetMacosAlignedVersion() >= MacosVersion(10, 10)) {
847 // os_trace requires the message (format parameter) to be a string literal.853 // os_trace requires the message (format parameter) to be a string literal.
848 if (internal_strncmp(SanitizerToolName, "AddressSanitizer",854 if (internal_strncmp(SanitizerToolName, "AddressSanitizer",
...@@ -860,6 +866,7 @@ void LogFullErrorReport(const char *buffer) {...@@ -860,6 +866,7 @@ void LogFullErrorReport(const char *buffer) {
860 if (common_flags()->log_to_syslog)866 if (common_flags()->log_to_syslog)
861 os_trace("Consult syslog for more information.");867 os_trace("Consult syslog for more information.");
862 }868 }
869#pragma clang diagnostic pop
863#endif870#endif
864871
865 // Log to syslog.872 // Log to syslog.
...@@ -970,8 +977,9 @@ static const char kDyldInsertLibraries[] = "DYLD_INSERT_LIBRARIES";...@@ -970,8 +977,9 @@ static const char kDyldInsertLibraries[] = "DYLD_INSERT_LIBRARIES";
970LowLevelAllocator allocator_for_env;977LowLevelAllocator allocator_for_env;
971978
972static bool ShouldCheckInterceptors() {979static bool ShouldCheckInterceptors() {
973 // Restrict "interceptors working?" check to ASan and TSan.980 // Restrict "interceptors working?" check
974 const char *sanitizer_names[] = {"AddressSanitizer", "ThreadSanitizer"};981 const char *sanitizer_names[] = {"AddressSanitizer", "ThreadSanitizer",
982 "RealtimeSanitizer"};
975 size_t count = sizeof(sanitizer_names) / sizeof(sanitizer_names[0]);983 size_t count = sizeof(sanitizer_names) / sizeof(sanitizer_names[0]);
976 for (size_t i = 0; i < count; i++) {984 for (size_t i = 0; i < count; i++) {
977 if (internal_strcmp(sanitizer_names[i], SanitizerToolName) == 0)985 if (internal_strcmp(sanitizer_names[i], SanitizerToolName) == 0)
lib/tsan/sanitizer_common/sanitizer_platform_interceptors.h+45-7
...@@ -84,6 +84,25 @@...@@ -84,6 +84,25 @@
84#define SI_NOT_MAC 184#define SI_NOT_MAC 1
85#endif85#endif
8686
87#if SANITIZER_APPLE
88# include <Availability.h>
89
90// aligned_alloc was introduced in OSX 10.15
91// Linking will fail when using an older SDK
92# if defined(__MAC_10_15)
93// macOS 10.15 is greater than our minimal deployment target. To ensure we
94// generate a weak reference so the dylib continues to work on older
95// systems, we need to forward declare the intercepted function as "weak
96// imports".
97SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
98 __sanitizer::usize __size);
99# define SI_MAC_SDK_10_15_AVAILABLE 1
100# else
101# define SI_MAC_SDK_10_15_AVAILABLE 0
102# endif // defined(__MAC_10_15)
103
104#endif // SANITIZER_APPLE
105
87#if SANITIZER_IOS106#if SANITIZER_IOS
88#define SI_IOS 1107#define SI_IOS 1
89#else108#else
...@@ -183,9 +202,16 @@...@@ -183,9 +202,16 @@
183#define SANITIZER_INTERCEPT_FPUTS SI_POSIX202#define SANITIZER_INTERCEPT_FPUTS SI_POSIX
184#define SANITIZER_INTERCEPT_PUTS SI_POSIX203#define SANITIZER_INTERCEPT_PUTS SI_POSIX
185204
205#define SANITIZER_INTERCEPT_CREAT64 (SI_GLIBC || SI_SOLARIS32)
206#define SANITIZER_INTERCEPT_FCNTL64 (SI_GLIBC || SI_SOLARIS32)
207#define SANITIZER_INTERCEPT_OPEN64 (SI_GLIBC || SI_SOLARIS32)
208#define SANITIZER_INTERCEPT_OPENAT64 (SI_GLIBC || SI_SOLARIS32)
209
186#define SANITIZER_INTERCEPT_PREAD64 (SI_GLIBC || SI_SOLARIS32)210#define SANITIZER_INTERCEPT_PREAD64 (SI_GLIBC || SI_SOLARIS32)
187#define SANITIZER_INTERCEPT_PWRITE64 (SI_GLIBC || SI_SOLARIS32)211#define SANITIZER_INTERCEPT_PWRITE64 (SI_GLIBC || SI_SOLARIS32)
188212
213#define SANITIZER_INTERCEPT_LSEEK64 (SI_GLIBC || SI_SOLARIS32)
214
189#define SANITIZER_INTERCEPT_READV SI_POSIX215#define SANITIZER_INTERCEPT_READV SI_POSIX
190#define SANITIZER_INTERCEPT_WRITEV SI_POSIX216#define SANITIZER_INTERCEPT_WRITEV SI_POSIX
191217
...@@ -232,8 +258,12 @@...@@ -232,8 +258,12 @@
232 (SI_FREEBSD || SI_NETBSD || SI_LINUX || SI_SOLARIS)258 (SI_FREEBSD || SI_NETBSD || SI_LINUX || SI_SOLARIS)
233#define SANITIZER_INTERCEPT_CLOCK_GETCPUCLOCKID \259#define SANITIZER_INTERCEPT_CLOCK_GETCPUCLOCKID \
234 (SI_LINUX || SI_FREEBSD || SI_NETBSD)260 (SI_LINUX || SI_FREEBSD || SI_NETBSD)
261// TODO: This should be SI_POSIX, adding glibc first until I have time
262// to verify all timer_t typedefs on other platforms.
263#define SANITIZER_INTERCEPT_TIMER_CREATE SI_GLIBC
235#define SANITIZER_INTERCEPT_GETITIMER SI_POSIX264#define SANITIZER_INTERCEPT_GETITIMER SI_POSIX
236#define SANITIZER_INTERCEPT_TIME SI_POSIX265#define SANITIZER_INTERCEPT_TIME SI_POSIX
266#define SANITIZER_INTERCEPT_TIMESPEC_GET SI_LINUX
237#define SANITIZER_INTERCEPT_GLOB (SI_GLIBC || SI_SOLARIS)267#define SANITIZER_INTERCEPT_GLOB (SI_GLIBC || SI_SOLARIS)
238#define SANITIZER_INTERCEPT_GLOB64 SI_GLIBC268#define SANITIZER_INTERCEPT_GLOB64 SI_GLIBC
239#define SANITIZER_INTERCEPT___B64_TO SI_LINUX_NOT_ANDROID269#define SANITIZER_INTERCEPT___B64_TO SI_LINUX_NOT_ANDROID
...@@ -274,8 +304,9 @@...@@ -274,8 +304,9 @@
274#if SI_LINUX_NOT_ANDROID && \304#if SI_LINUX_NOT_ANDROID && \
275 (defined(__i386) || defined(__x86_64) || defined(__mips64) || \305 (defined(__i386) || defined(__x86_64) || defined(__mips64) || \
276 defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \306 defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \
277 defined(__s390__) || defined(__loongarch__) || SANITIZER_RISCV64)307 defined(__s390__) || defined(__loongarch__) || SANITIZER_RISCV64 || \
278#define SANITIZER_INTERCEPT_PTRACE 1308 defined(__sparc__))
309# define SANITIZER_INTERCEPT_PTRACE 1
279#else310#else
280#define SANITIZER_INTERCEPT_PTRACE 0311#define SANITIZER_INTERCEPT_PTRACE 0
281#endif312#endif
...@@ -314,6 +345,8 @@...@@ -314,6 +345,8 @@
314#define SANITIZER_INTERCEPT_GETGROUPS SI_POSIX345#define SANITIZER_INTERCEPT_GETGROUPS SI_POSIX
315#define SANITIZER_INTERCEPT_POLL SI_POSIX346#define SANITIZER_INTERCEPT_POLL SI_POSIX
316#define SANITIZER_INTERCEPT_PPOLL SI_LINUX_NOT_ANDROID || SI_SOLARIS347#define SANITIZER_INTERCEPT_PPOLL SI_LINUX_NOT_ANDROID || SI_SOLARIS
348#define SANITIZER_INTERCEPT_EPOLL (SI_LINUX)
349#define SANITIZER_INTERCEPT_KQUEUE (SI_FREEBSD || SI_NETBSD || SI_MAC)
317#define SANITIZER_INTERCEPT_WORDEXP \350#define SANITIZER_INTERCEPT_WORDEXP \
318 (SI_FREEBSD || SI_NETBSD || (SI_MAC && !SI_IOS) || SI_LINUX_NOT_ANDROID || \351 (SI_FREEBSD || SI_NETBSD || (SI_MAC && !SI_IOS) || SI_LINUX_NOT_ANDROID || \
319 SI_SOLARIS)352 SI_SOLARIS)
...@@ -494,7 +527,8 @@...@@ -494,7 +527,8 @@
494#define SANITIZER_INTERCEPT_PVALLOC (SI_GLIBC || SI_ANDROID)527#define SANITIZER_INTERCEPT_PVALLOC (SI_GLIBC || SI_ANDROID)
495#define SANITIZER_INTERCEPT_CFREE (SI_GLIBC && !SANITIZER_RISCV64)528#define SANITIZER_INTERCEPT_CFREE (SI_GLIBC && !SANITIZER_RISCV64)
496#define SANITIZER_INTERCEPT_REALLOCARRAY SI_POSIX529#define SANITIZER_INTERCEPT_REALLOCARRAY SI_POSIX
497#define SANITIZER_INTERCEPT_ALIGNED_ALLOC (!SI_MAC)530#define SANITIZER_INTERCEPT_ALIGNED_ALLOC \
531 (!SI_MAC || SI_MAC_SDK_10_15_AVAILABLE)
498#define SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE (!SI_MAC && !SI_NETBSD)532#define SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE (!SI_MAC && !SI_NETBSD)
499#define SANITIZER_INTERCEPT_MCHECK_MPROBE SI_LINUX_NOT_ANDROID533#define SANITIZER_INTERCEPT_MCHECK_MPROBE SI_LINUX_NOT_ANDROID
500#define SANITIZER_INTERCEPT_WCSLEN 1534#define SANITIZER_INTERCEPT_WCSLEN 1
...@@ -559,10 +593,8 @@...@@ -559,10 +593,8 @@
559#define SANITIZER_INTERCEPT_SHA1 SI_NETBSD593#define SANITIZER_INTERCEPT_SHA1 SI_NETBSD
560#define SANITIZER_INTERCEPT_MD4 SI_NETBSD594#define SANITIZER_INTERCEPT_MD4 SI_NETBSD
561#define SANITIZER_INTERCEPT_RMD160 SI_NETBSD595#define SANITIZER_INTERCEPT_RMD160 SI_NETBSD
562#define SANITIZER_INTERCEPT_MD5 (SI_NETBSD || SI_FREEBSD)596#define SANITIZER_INTERCEPT_FSEEK SI_POSIX
563#define SANITIZER_INTERCEPT_FSEEK (SI_NETBSD || SI_FREEBSD)
564#define SANITIZER_INTERCEPT_MD2 SI_NETBSD597#define SANITIZER_INTERCEPT_MD2 SI_NETBSD
565#define SANITIZER_INTERCEPT_SHA2 (SI_NETBSD || SI_FREEBSD)
566#define SANITIZER_INTERCEPT_CDB SI_NETBSD598#define SANITIZER_INTERCEPT_CDB SI_NETBSD
567#define SANITIZER_INTERCEPT_VIS (SI_NETBSD || SI_FREEBSD)599#define SANITIZER_INTERCEPT_VIS (SI_NETBSD || SI_FREEBSD)
568#define SANITIZER_INTERCEPT_POPEN SI_POSIX600#define SANITIZER_INTERCEPT_POPEN SI_POSIX
...@@ -601,7 +633,13 @@...@@ -601,7 +633,13 @@
601// FIXME: also available from musl 1.2.5633// FIXME: also available from musl 1.2.5
602#define SANITIZER_INTERCEPT_PREADV2 (SI_LINUX && __GLIBC_PREREQ(2, 26))634#define SANITIZER_INTERCEPT_PREADV2 (SI_LINUX && __GLIBC_PREREQ(2, 26))
603#define SANITIZER_INTERCEPT_PWRITEV2 (SI_LINUX && __GLIBC_PREREQ(2, 26))635#define SANITIZER_INTERCEPT_PWRITEV2 (SI_LINUX && __GLIBC_PREREQ(2, 26))
604636#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && \
637 __MAC_OS_X_VERSION_MIN_REQUIRED >= 130000
638# define SI_MAC_OS_DEPLOYMENT_MIN_13_00 1
639#else
640# define SI_MAC_OS_DEPLOYMENT_MIN_13_00 0
641#endif
642#define SANITIZER_INTERCEPT_FREADLINK (SI_MAC && SI_MAC_OS_DEPLOYMENT_MIN_13_00)
605// This macro gives a way for downstream users to override the above643// This macro gives a way for downstream users to override the above
606// interceptor macros irrespective of the platform they are on. They have644// interceptor macros irrespective of the platform they are on. They have
607// to do two things:645// to do two things:
lib/tsan/sanitizer_common/sanitizer_platform_limits_netbsd.cpp+1-2
...@@ -547,6 +547,7 @@ unsigned pid_t_sz = sizeof(pid_t);...@@ -547,6 +547,7 @@ unsigned pid_t_sz = sizeof(pid_t);
547unsigned timeval_sz = sizeof(timeval);547unsigned timeval_sz = sizeof(timeval);
548unsigned uid_t_sz = sizeof(uid_t);548unsigned uid_t_sz = sizeof(uid_t);
549unsigned gid_t_sz = sizeof(gid_t);549unsigned gid_t_sz = sizeof(gid_t);
550unsigned fpos_t_sz = sizeof(fpos_t);
550unsigned mbstate_t_sz = sizeof(mbstate_t);551unsigned mbstate_t_sz = sizeof(mbstate_t);
551unsigned sigset_t_sz = sizeof(sigset_t);552unsigned sigset_t_sz = sizeof(sigset_t);
552unsigned struct_timezone_sz = sizeof(struct timezone);553unsigned struct_timezone_sz = sizeof(struct timezone);
...@@ -2487,8 +2488,6 @@ const unsigned RMD160_return_length = RMD160_DIGEST_STRING_LENGTH;...@@ -2487,8 +2488,6 @@ const unsigned RMD160_return_length = RMD160_DIGEST_STRING_LENGTH;
2487const unsigned MD5_CTX_sz = sizeof(MD5_CTX);2488const unsigned MD5_CTX_sz = sizeof(MD5_CTX);
2488const unsigned MD5_return_length = MD5_DIGEST_STRING_LENGTH;2489const unsigned MD5_return_length = MD5_DIGEST_STRING_LENGTH;
24892490
2490const unsigned fpos_t_sz = sizeof(fpos_t);
2491
2492const unsigned MD2_CTX_sz = sizeof(MD2_CTX);2491const unsigned MD2_CTX_sz = sizeof(MD2_CTX);
2493const unsigned MD2_return_length = MD2_DIGEST_STRING_LENGTH;2492const unsigned MD2_return_length = MD2_DIGEST_STRING_LENGTH;
24942493
lib/tsan/sanitizer_common/sanitizer_platform_limits_netbsd.h+1-2
...@@ -36,6 +36,7 @@ extern unsigned pid_t_sz;...@@ -36,6 +36,7 @@ extern unsigned pid_t_sz;
36extern unsigned timeval_sz;36extern unsigned timeval_sz;
37extern unsigned uid_t_sz;37extern unsigned uid_t_sz;
38extern unsigned gid_t_sz;38extern unsigned gid_t_sz;
39extern unsigned fpos_t_sz;
39extern unsigned mbstate_t_sz;40extern unsigned mbstate_t_sz;
40extern unsigned struct_timezone_sz;41extern unsigned struct_timezone_sz;
41extern unsigned struct_tms_sz;42extern unsigned struct_tms_sz;
...@@ -2335,8 +2336,6 @@ extern const unsigned RMD160_return_length;...@@ -2335,8 +2336,6 @@ extern const unsigned RMD160_return_length;
2335extern const unsigned MD5_CTX_sz;2336extern const unsigned MD5_CTX_sz;
2336extern const unsigned MD5_return_length;2337extern const unsigned MD5_return_length;
23372338
2338extern const unsigned fpos_t_sz;
2339
2340extern const unsigned MD2_CTX_sz;2339extern const unsigned MD2_CTX_sz;
2341extern const unsigned MD2_return_length;2340extern const unsigned MD2_return_length;
23422341
lib/tsan/sanitizer_common/sanitizer_platform_limits_posix.cpp+35-26
...@@ -94,8 +94,9 @@...@@ -94,8 +94,9 @@
94#if SANITIZER_LINUX94#if SANITIZER_LINUX
95# include <utime.h>95# include <utime.h>
96# include <sys/ptrace.h>96# include <sys/ptrace.h>
97# if defined(__mips64) || defined(__aarch64__) || defined(__arm__) || \97# if defined(__mips64) || defined(__aarch64__) || defined(__arm__) || \
98 defined(__hexagon__) || defined(__loongarch__) ||SANITIZER_RISCV6498 defined(__hexagon__) || defined(__loongarch__) || SANITIZER_RISCV64 || \
99 defined(__sparc__)
99# include <asm/ptrace.h>100# include <asm/ptrace.h>
100# ifdef __arm__101# ifdef __arm__
101typedef struct user_fpregs elf_fpregset_t;102typedef struct user_fpregs elf_fpregset_t;
...@@ -117,15 +118,16 @@ typedef struct user_fpregs elf_fpregset_t;...@@ -117,15 +118,16 @@ typedef struct user_fpregs elf_fpregset_t;
117#if SANITIZER_LINUX118#if SANITIZER_LINUX
118#if SANITIZER_GLIBC119#if SANITIZER_GLIBC
119#include <fstab.h>120#include <fstab.h>
120#include <net/if_ppp.h>121# include <linux/filter.h>
121#include <netax25/ax25.h>122# include <net/if_ppp.h>
122#include <netipx/ipx.h>123# include <netax25/ax25.h>
123#include <netrom/netrom.h>124# include <netipx/ipx.h>
124#include <obstack.h>125# include <netrom/netrom.h>
125#if HAVE_RPC_XDR_H126# include <obstack.h>
126# include <rpc/xdr.h>127# if HAVE_RPC_XDR_H
127#endif128# include <rpc/xdr.h>
128#include <scsi/scsi.h>129# endif
130# include <scsi/scsi.h>
129#else131#else
130#include <linux/if_ppp.h>132#include <linux/if_ppp.h>
131#include <linux/kd.h>133#include <linux/kd.h>
...@@ -358,11 +360,12 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);...@@ -358,11 +360,12 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
358 const int wordexp_wrde_dooffs = WRDE_DOOFFS;360 const int wordexp_wrde_dooffs = WRDE_DOOFFS;
359# endif // !SANITIZER_ANDROID361# endif // !SANITIZER_ANDROID
360362
361#if SANITIZER_LINUX && !SANITIZER_ANDROID && \363# if SANITIZER_LINUX && !SANITIZER_ANDROID && \
362 (defined(__i386) || defined(__x86_64) || defined(__mips64) || \364 (defined(__i386) || defined(__x86_64) || defined(__mips64) || \
363 defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \365 defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \
364 defined(__s390__) || defined(__loongarch__)|| SANITIZER_RISCV64)366 defined(__s390__) || defined(__loongarch__) || SANITIZER_RISCV64 || \
365#if defined(__mips64) || defined(__powerpc64__) || defined(__arm__)367 defined(__sparc__))
368# if defined(__mips64) || defined(__powerpc64__) || defined(__arm__)
366 unsigned struct_user_regs_struct_sz = sizeof(struct pt_regs);369 unsigned struct_user_regs_struct_sz = sizeof(struct pt_regs);
367 unsigned struct_user_fpregs_struct_sz = sizeof(elf_fpregset_t);370 unsigned struct_user_fpregs_struct_sz = sizeof(elf_fpregset_t);
368#elif SANITIZER_RISCV64371#elif SANITIZER_RISCV64
...@@ -377,19 +380,22 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);...@@ -377,19 +380,22 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
377#elif defined(__s390__)380#elif defined(__s390__)
378 unsigned struct_user_regs_struct_sz = sizeof(struct _user_regs_struct);381 unsigned struct_user_regs_struct_sz = sizeof(struct _user_regs_struct);
379 unsigned struct_user_fpregs_struct_sz = sizeof(struct _user_fpregs_struct);382 unsigned struct_user_fpregs_struct_sz = sizeof(struct _user_fpregs_struct);
380#else383# elif defined(__sparc__)
384 unsigned struct_user_regs_struct_sz = sizeof(struct sunos_regs);
385 unsigned struct_user_fpregs_struct_sz = sizeof(struct sunos_fp);
386# else
381 unsigned struct_user_regs_struct_sz = sizeof(struct user_regs_struct);387 unsigned struct_user_regs_struct_sz = sizeof(struct user_regs_struct);
382 unsigned struct_user_fpregs_struct_sz = sizeof(struct user_fpregs_struct);388 unsigned struct_user_fpregs_struct_sz = sizeof(struct user_fpregs_struct);
383#endif // __mips64 || __powerpc64__ || __aarch64__ || __loongarch__389# endif // __mips64 || __powerpc64__ || __aarch64__ || __loongarch__
384#if defined(__x86_64) || defined(__mips64) || defined(__powerpc64__) || \390# if defined(__x86_64) || defined(__mips64) || defined(__powerpc64__) || \
385 defined(__aarch64__) || defined(__arm__) || defined(__s390__) || \391 defined(__aarch64__) || defined(__arm__) || defined(__s390__) || \
386 defined(__loongarch__) || SANITIZER_RISCV64392 defined(__loongarch__) || SANITIZER_RISCV64 || defined(__sparc__)
387 unsigned struct_user_fpxregs_struct_sz = 0;393 unsigned struct_user_fpxregs_struct_sz = 0;
388#else394#else
389 unsigned struct_user_fpxregs_struct_sz = sizeof(struct user_fpxregs_struct);395 unsigned struct_user_fpxregs_struct_sz = sizeof(struct user_fpxregs_struct);
390#endif // __x86_64 || __mips64 || __powerpc64__ || __aarch64__ || __arm__396#endif // __x86_64 || __mips64 || __powerpc64__ || __aarch64__ || __arm__
391// || __s390__ || __loongarch__397 // || __s390__ || __loongarch__ || SANITIZER_RISCV64 || __sparc__
392#ifdef __arm__398# ifdef __arm__
393 unsigned struct_user_vfpregs_struct_sz = ARM_VFPREGS_SIZE;399 unsigned struct_user_vfpregs_struct_sz = ARM_VFPREGS_SIZE;
394#else400#else
395 unsigned struct_user_vfpregs_struct_sz = 0;401 unsigned struct_user_vfpregs_struct_sz = 0;
...@@ -531,13 +537,16 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);...@@ -531,13 +537,16 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
531537
532 unsigned struct_audio_buf_info_sz = sizeof(struct audio_buf_info);538 unsigned struct_audio_buf_info_sz = sizeof(struct audio_buf_info);
533 unsigned struct_ppp_stats_sz = sizeof(struct ppp_stats);539 unsigned struct_ppp_stats_sz = sizeof(struct ppp_stats);
534#endif // SANITIZER_GLIBC540 unsigned struct_sock_fprog_sz = sizeof(struct sock_fprog);
541# endif // SANITIZER_GLIBC
535542
536#if !SANITIZER_ANDROID && !SANITIZER_APPLE543# if !SANITIZER_ANDROID && !SANITIZER_APPLE
537 unsigned struct_sioc_sg_req_sz = sizeof(struct sioc_sg_req);544 unsigned struct_sioc_sg_req_sz = sizeof(struct sioc_sg_req);
538 unsigned struct_sioc_vif_req_sz = sizeof(struct sioc_vif_req);545 unsigned struct_sioc_vif_req_sz = sizeof(struct sioc_vif_req);
539#endif546#endif
540547
548 unsigned fpos_t_sz = sizeof(fpos_t);
549
541 const unsigned long __sanitizer_bufsiz = BUFSIZ;550 const unsigned long __sanitizer_bufsiz = BUFSIZ;
542551
543 const unsigned IOCTL_NOT_PRESENT = 0;552 const unsigned IOCTL_NOT_PRESENT = 0;
...@@ -1084,7 +1093,7 @@ CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_len);...@@ -1084,7 +1093,7 @@ CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_len);
1084CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_level);1093CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_level);
1085CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_type);1094CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_type);
10861095
1087#if SANITIZER_LINUX && (__ANDROID_API__ >= 21 || __GLIBC_PREREQ (2, 14))1096# if SANITIZER_LINUX && (SANITIZER_ANDROID || __GLIBC_PREREQ(2, 14))
1088CHECK_TYPE_SIZE(mmsghdr);1097CHECK_TYPE_SIZE(mmsghdr);
1089CHECK_SIZE_AND_OFFSET(mmsghdr, msg_hdr);1098CHECK_SIZE_AND_OFFSET(mmsghdr, msg_hdr);
1090CHECK_SIZE_AND_OFFSET(mmsghdr, msg_len);1099CHECK_SIZE_AND_OFFSET(mmsghdr, msg_len);
lib/tsan/sanitizer_common/sanitizer_platform_limits_posix.h+49-13
...@@ -98,10 +98,13 @@ const unsigned struct_kernel_stat64_sz = 104;...@@ -98,10 +98,13 @@ const unsigned struct_kernel_stat64_sz = 104;
98const unsigned struct_kernel_stat_sz = 144;98const unsigned struct_kernel_stat_sz = 144;
99const unsigned struct_kernel_stat64_sz = 104;99const unsigned struct_kernel_stat64_sz = 104;
100#elif defined(__mips__)100#elif defined(__mips__)
101const unsigned struct_kernel_stat_sz =101const unsigned struct_kernel_stat_sz = SANITIZER_ANDROID
102 SANITIZER_ANDROID102 ? FIRST_32_SECOND_64(104, 128)
103 ? FIRST_32_SECOND_64(104, 128)103# if defined(_ABIN32) && _MIPS_SIM == _ABIN32
104 : FIRST_32_SECOND_64((_MIPS_SIM == _ABIN32) ? 176 : 160, 216);104 : FIRST_32_SECOND_64(176, 216);
105# else
106 : FIRST_32_SECOND_64(160, 216);
107# endif
105const unsigned struct_kernel_stat64_sz = 104;108const unsigned struct_kernel_stat64_sz = 104;
106#elif defined(__s390__) && !defined(__s390x__)109#elif defined(__s390__) && !defined(__s390x__)
107const unsigned struct_kernel_stat_sz = 64;110const unsigned struct_kernel_stat_sz = 64;
...@@ -313,7 +316,7 @@ extern unsigned struct_statvfs_sz;...@@ -313,7 +316,7 @@ extern unsigned struct_statvfs_sz;
313316
314struct __sanitizer_iovec {317struct __sanitizer_iovec {
315 void *iov_base;318 void *iov_base;
316 uptr iov_len;319 usize iov_len;
317};320};
318321
319#if !SANITIZER_ANDROID322#if !SANITIZER_ANDROID
...@@ -389,6 +392,16 @@ typedef long __sanitizer_time_t;...@@ -389,6 +392,16 @@ typedef long __sanitizer_time_t;
389392
390typedef long __sanitizer_suseconds_t;393typedef long __sanitizer_suseconds_t;
391394
395struct __sanitizer_timespec {
396 __sanitizer_time_t tv_sec; /* seconds */
397 u64 tv_nsec; /* nanoseconds */
398};
399
400struct __sanitizer_itimerspec {
401 struct __sanitizer_timespec it_interval; /* timer period */
402 struct __sanitizer_timespec it_value; /* timer expiration */
403};
404
392struct __sanitizer_timeval {405struct __sanitizer_timeval {
393 __sanitizer_time_t tv_sec;406 __sanitizer_time_t tv_sec;
394 __sanitizer_suseconds_t tv_usec;407 __sanitizer_suseconds_t tv_usec;
...@@ -513,6 +526,7 @@ struct __sanitizer_dirent64 {...@@ -513,6 +526,7 @@ struct __sanitizer_dirent64 {
513 unsigned short d_reclen;526 unsigned short d_reclen;
514 // more fields that we don't care about527 // more fields that we don't care about
515};528};
529extern unsigned struct_sock_fprog_sz;
516#endif530#endif
517531
518#if defined(__x86_64__) && !defined(_LP64)532#if defined(__x86_64__) && !defined(_LP64)
...@@ -590,7 +604,7 @@ struct __sanitizer_siginfo_pad {...@@ -590,7 +604,7 @@ struct __sanitizer_siginfo_pad {
590#if SANITIZER_LINUX604#if SANITIZER_LINUX
591# define SANITIZER_HAS_SIGINFO 1605# define SANITIZER_HAS_SIGINFO 1
592union __sanitizer_siginfo {606union __sanitizer_siginfo {
593 struct {607 __extension__ struct {
594 int si_signo;608 int si_signo;
595# if SANITIZER_MIPS609# if SANITIZER_MIPS
596 int si_code;610 int si_code;
...@@ -855,10 +869,11 @@ typedef void __sanitizer_FILE;...@@ -855,10 +869,11 @@ typedef void __sanitizer_FILE;
855# define SANITIZER_HAS_STRUCT_FILE 0869# define SANITIZER_HAS_STRUCT_FILE 0
856#endif870#endif
857871
858#if SANITIZER_LINUX && !SANITIZER_ANDROID && \872# if SANITIZER_LINUX && !SANITIZER_ANDROID && \
859 (defined(__i386) || defined(__x86_64) || defined(__mips64) || \873 (defined(__i386) || defined(__x86_64) || defined(__mips64) || \
860 defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \874 defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \
861 defined(__s390__) || defined(__loongarch__) || SANITIZER_RISCV64)875 defined(__s390__) || defined(__loongarch__) || SANITIZER_RISCV64 || \
876 defined(__sparc__))
862extern unsigned struct_user_regs_struct_sz;877extern unsigned struct_user_regs_struct_sz;
863extern unsigned struct_user_fpregs_struct_sz;878extern unsigned struct_user_fpregs_struct_sz;
864extern unsigned struct_user_fpxregs_struct_sz;879extern unsigned struct_user_fpxregs_struct_sz;
...@@ -880,9 +895,24 @@ extern int ptrace_setsiginfo;...@@ -880,9 +895,24 @@ extern int ptrace_setsiginfo;
880extern int ptrace_getregset;895extern int ptrace_getregset;
881extern int ptrace_setregset;896extern int ptrace_setregset;
882extern int ptrace_geteventmsg;897extern int ptrace_geteventmsg;
883#endif
884898
885#if SANITIZER_LINUX && !SANITIZER_ANDROID899// Helper for the ptrace interceptor.
900template <class T>
901inline T ptrace_data_arg(int request, T addr, T data) {
902# if SANITIZER_LINUX && SANITIZER_SPARC
903 // As described in ptrace(2), the meanings of addr and data are reversed
904 // for the PTRACE_GETREGS, PTRACE_GETFPREGS, PTRACE_GETREGS, and
905 // PTRACE_GETFPREGS requests on Linux/sparc64.
906 if (request == ptrace_getregs || request == ptrace_getfpregs ||
907 request == ptrace_setregs || request == ptrace_setfpregs)
908 return addr;
909 else
910# endif
911 return data;
912}
913# endif
914
915# if SANITIZER_LINUX && !SANITIZER_ANDROID
886extern unsigned struct_shminfo_sz;916extern unsigned struct_shminfo_sz;
887extern unsigned struct_shm_info_sz;917extern unsigned struct_shm_info_sz;
888extern int shmctl_ipc_stat;918extern int shmctl_ipc_stat;
...@@ -1050,7 +1080,7 @@ extern unsigned struct_serial_struct_sz;...@@ -1050,7 +1080,7 @@ extern unsigned struct_serial_struct_sz;
1050extern unsigned struct_sockaddr_ax25_sz;1080extern unsigned struct_sockaddr_ax25_sz;
1051extern unsigned struct_unimapdesc_sz;1081extern unsigned struct_unimapdesc_sz;
1052extern unsigned struct_unimapinit_sz;1082extern unsigned struct_unimapinit_sz;
1053#endif // SANITIZER_LINUX && !SANITIZER_ANDROID1083# endif // SANITIZER_LINUX && !SANITIZER_ANDROID
10541084
1055extern const unsigned long __sanitizer_bufsiz;1085extern const unsigned long __sanitizer_bufsiz;
10561086
...@@ -1064,6 +1094,8 @@ extern unsigned struct_sioc_sg_req_sz;...@@ -1064,6 +1094,8 @@ extern unsigned struct_sioc_sg_req_sz;
1064extern unsigned struct_sioc_vif_req_sz;1094extern unsigned struct_sioc_vif_req_sz;
1065#endif1095#endif
10661096
1097extern unsigned fpos_t_sz;
1098
1067// ioctl request identifiers1099// ioctl request identifiers
10681100
1069// A special value to mark ioctls that are not present on the target platform,1101// A special value to mark ioctls that are not present on the target platform,
...@@ -1500,6 +1532,10 @@ extern const int si_SEGV_ACCERR;...@@ -1500,6 +1532,10 @@ extern const int si_SEGV_ACCERR;
15001532
1501#define SIGACTION_SYMNAME sigaction1533#define SIGACTION_SYMNAME sigaction
15021534
1535# if SANITIZER_LINUX
1536typedef void *__sanitizer_timer_t;
1537# endif
1538
1503#endif // SANITIZER_LINUX || SANITIZER_APPLE1539#endif // SANITIZER_LINUX || SANITIZER_APPLE
15041540
1505#endif1541#endif
lib/tsan/sanitizer_common/sanitizer_platform_limits_solaris.cpp+3
...@@ -32,6 +32,7 @@...@@ -32,6 +32,7 @@
32#include <semaphore.h>32#include <semaphore.h>
33#include <signal.h>33#include <signal.h>
34#include <stddef.h>34#include <stddef.h>
35#include <stdio.h>
35#include <sys/ethernet.h>36#include <sys/ethernet.h>
36#include <sys/filio.h>37#include <sys/filio.h>
37#include <sys/ipc.h>38#include <sys/ipc.h>
...@@ -135,6 +136,8 @@ namespace __sanitizer {...@@ -135,6 +136,8 @@ namespace __sanitizer {
135 unsigned struct_sioc_sg_req_sz = sizeof(struct sioc_sg_req);136 unsigned struct_sioc_sg_req_sz = sizeof(struct sioc_sg_req);
136 unsigned struct_sioc_vif_req_sz = sizeof(struct sioc_vif_req);137 unsigned struct_sioc_vif_req_sz = sizeof(struct sioc_vif_req);
137138
139 unsigned fpos_t_sz = sizeof(fpos_t);
140
138 const unsigned IOCTL_NOT_PRESENT = 0;141 const unsigned IOCTL_NOT_PRESENT = 0;
139142
140 unsigned IOCTL_FIOASYNC = FIOASYNC;143 unsigned IOCTL_FIOASYNC = FIOASYNC;
lib/tsan/sanitizer_common/sanitizer_platform_limits_solaris.h+2
...@@ -418,6 +418,8 @@ extern unsigned struct_winsize_sz;...@@ -418,6 +418,8 @@ extern unsigned struct_winsize_sz;
418extern unsigned struct_sioc_sg_req_sz;418extern unsigned struct_sioc_sg_req_sz;
419extern unsigned struct_sioc_vif_req_sz;419extern unsigned struct_sioc_vif_req_sz;
420420
421extern unsigned fpos_t_sz;
422
421// ioctl request identifiers423// ioctl request identifiers
422424
423// A special value to mark ioctls that are not present on the target platform,425// A special value to mark ioctls that are not present on the target platform,
lib/tsan/sanitizer_common/sanitizer_posix.cpp+9-1
...@@ -353,7 +353,15 @@ bool ShouldMockFailureToOpen(const char *path) {...@@ -353,7 +353,15 @@ bool ShouldMockFailureToOpen(const char *path) {
353 internal_strncmp(path, "/proc/", 6) == 0;353 internal_strncmp(path, "/proc/", 6) == 0;
354}354}
355355
356#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_GO356bool OpenReadsVaArgs(int oflag) {
357# ifdef O_TMPFILE
358 return (oflag & (O_CREAT | O_TMPFILE)) != 0;
359# else
360 return (oflag & O_CREAT) != 0;
361# endif
362}
363
364# if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_GO
357int GetNamedMappingFd(const char *name, uptr size, int *flags) {365int GetNamedMappingFd(const char *name, uptr size, int *flags) {
358 if (!common_flags()->decorate_proc_maps || !name)366 if (!common_flags()->decorate_proc_maps || !name)
359 return -1;367 return -1;
lib/tsan/sanitizer_common/sanitizer_posix.h+5-1
...@@ -28,6 +28,9 @@ namespace __sanitizer {...@@ -28,6 +28,9 @@ namespace __sanitizer {
28// Don't use directly, use __sanitizer::OpenFile() instead.28// Don't use directly, use __sanitizer::OpenFile() instead.
29uptr internal_open(const char *filename, int flags);29uptr internal_open(const char *filename, int flags);
30uptr internal_open(const char *filename, int flags, u32 mode);30uptr internal_open(const char *filename, int flags, u32 mode);
31# if SANITIZER_FREEBSD
32uptr internal_close_range(fd_t lowfd, fd_t highfd, int flags);
33# endif
31uptr internal_close(fd_t fd);34uptr internal_close(fd_t fd);
3235
33uptr internal_read(fd_t fd, void *buf, uptr count);36uptr internal_read(fd_t fd, void *buf, uptr count);
...@@ -86,7 +89,7 @@ int internal_pthread_join(void *th, void **ret);...@@ -86,7 +89,7 @@ int internal_pthread_join(void *th, void **ret);
86 return REAL(pthread_create)(th, attr, callback, param); \89 return REAL(pthread_create)(th, attr, callback, param); \
87 } \90 } \
88 int internal_pthread_join(void *th, void **ret) { \91 int internal_pthread_join(void *th, void **ret) { \
89 return REAL(pthread_join(th, ret)); \92 return REAL(pthread_join)(th, ret); \
90 } \93 } \
91 } // namespace __sanitizer94 } // namespace __sanitizer
9295
...@@ -108,6 +111,7 @@ bool IsStateDetached(int state);...@@ -108,6 +111,7 @@ bool IsStateDetached(int state);
108fd_t ReserveStandardFds(fd_t fd);111fd_t ReserveStandardFds(fd_t fd);
109112
110bool ShouldMockFailureToOpen(const char *path);113bool ShouldMockFailureToOpen(const char *path);
114bool OpenReadsVaArgs(int oflag);
111115
112// Create a non-file mapping with a given /proc/self/maps name.116// Create a non-file mapping with a given /proc/self/maps name.
113uptr MmapNamed(void *addr, uptr length, int prot, int flags, const char *name);117uptr MmapNamed(void *addr, uptr length, int prot, int flags, const char *name);
lib/tsan/sanitizer_common/sanitizer_posix_libcdep.cpp+82-18
...@@ -288,26 +288,86 @@ bool SignalContext::IsStackOverflow() const {...@@ -288,26 +288,86 @@ bool SignalContext::IsStackOverflow() const {
288288
289#endif // SANITIZER_GO289#endif // SANITIZER_GO
290290
291static void SetNonBlock(int fd) {
292 int res = fcntl(fd, F_GETFL, 0);
293 CHECK(!internal_iserror(res, nullptr));
294
295 res |= O_NONBLOCK;
296 res = fcntl(fd, F_SETFL, res);
297 CHECK(!internal_iserror(res, nullptr));
298}
299
291bool IsAccessibleMemoryRange(uptr beg, uptr size) {300bool IsAccessibleMemoryRange(uptr beg, uptr size) {
292 uptr page_size = GetPageSizeCached();301 while (size) {
293 // Checking too large memory ranges is slow.302 // `read` from `fds[0]` into a dummy buffer to free up the pipe buffer for
294 CHECK_LT(size, page_size * 10);303 // more `write` is slower than just recreating a pipe.
295 int sock_pair[2];304 int fds[2];
296 if (pipe(sock_pair))305 CHECK_EQ(0, pipe(fds));
297 return false;306
298 uptr bytes_written =307 auto cleanup = at_scope_exit([&]() {
299 internal_write(sock_pair[1], reinterpret_cast<void *>(beg), size);308 internal_close(fds[0]);
300 int write_errno;309 internal_close(fds[1]);
301 bool result;310 });
302 if (internal_iserror(bytes_written, &write_errno)) {311
303 CHECK_EQ(EFAULT, write_errno);312 SetNonBlock(fds[1]);
304 result = false;313
305 } else {314 int write_errno;
306 result = (bytes_written == size);315 uptr w = internal_write(fds[1], reinterpret_cast<char *>(beg), size);
316 if (internal_iserror(w, &write_errno)) {
317 if (write_errno == EINTR)
318 continue;
319 CHECK_EQ(EFAULT, write_errno);
320 return false;
321 }
322 size -= w;
323 beg += w;
324 }
325
326 return true;
327}
328
329bool TryMemCpy(void *dest, const void *src, uptr n) {
330 if (!n)
331 return true;
332 int fds[2];
333 CHECK_EQ(0, pipe(fds));
334
335 auto cleanup = at_scope_exit([&]() {
336 internal_close(fds[0]);
337 internal_close(fds[1]);
338 });
339
340 SetNonBlock(fds[0]);
341 SetNonBlock(fds[1]);
342
343 char *d = static_cast<char *>(dest);
344 const char *s = static_cast<const char *>(src);
345
346 while (n) {
347 int e;
348 uptr w = internal_write(fds[1], s, n);
349 if (internal_iserror(w, &e)) {
350 if (e == EINTR)
351 continue;
352 CHECK_EQ(EFAULT, e);
353 return false;
354 }
355 s += w;
356 n -= w;
357
358 while (w) {
359 uptr r = internal_read(fds[0], d, w);
360 if (internal_iserror(r, &e)) {
361 CHECK_EQ(EINTR, e);
362 continue;
363 }
364
365 d += r;
366 w -= r;
367 }
307 }368 }
308 internal_close(sock_pair[0]);369
309 internal_close(sock_pair[1]);370 return true;
310 return result;
311}371}
312372
313void PlatformPrepareForSandboxing(void *args) {373void PlatformPrepareForSandboxing(void *args) {
...@@ -483,7 +543,11 @@ pid_t StartSubprocess(const char *program, const char *const argv[],...@@ -483,7 +543,11 @@ pid_t StartSubprocess(const char *program, const char *const argv[],
483 internal_close(stderr_fd);543 internal_close(stderr_fd);
484 }544 }
485545
546# if SANITIZER_FREEBSD
547 internal_close_range(3, ~static_cast<fd_t>(0), 0);
548# else
486 for (int fd = sysconf(_SC_OPEN_MAX); fd > 2; fd--) internal_close(fd);549 for (int fd = sysconf(_SC_OPEN_MAX); fd > 2; fd--) internal_close(fd);
550# endif
487551
488 internal_execve(program, const_cast<char **>(&argv[0]),552 internal_execve(program, const_cast<char **>(&argv[0]),
489 const_cast<char *const *>(envp));553 const_cast<char *const *>(envp));
lib/tsan/sanitizer_common/sanitizer_procmaps_mac.cpp+3-1
...@@ -433,7 +433,9 @@ void MemoryMappingLayout::DumpListOfModules(...@@ -433,7 +433,9 @@ void MemoryMappingLayout::DumpListOfModules(
433 MemoryMappedSegmentData data;433 MemoryMappedSegmentData data;
434 segment.data_ = &data;434 segment.data_ = &data;
435 while (Next(&segment)) {435 while (Next(&segment)) {
436 if (segment.filename[0] == '\0') continue;436 // skip the __PAGEZERO segment, its vmsize is 0
437 if (segment.filename[0] == '\0' || (segment.start == segment.end))
438 continue;
437 LoadedModule *cur_module = nullptr;439 LoadedModule *cur_module = nullptr;
438 if (!modules->empty() &&440 if (!modules->empty() &&
439 0 == internal_strcmp(segment.filename, modules->back().full_name())) {441 0 == internal_strcmp(segment.filename, modules->back().full_name())) {
lib/tsan/sanitizer_common/sanitizer_procmaps_solaris.cpp+4
...@@ -11,6 +11,10 @@...@@ -11,6 +11,10 @@
1111
12// Before Solaris 11.4, <procfs.h> doesn't work in a largefile environment.12// Before Solaris 11.4, <procfs.h> doesn't work in a largefile environment.
13#undef _FILE_OFFSET_BITS13#undef _FILE_OFFSET_BITS
14
15// Avoid conflict between `_TIME_BITS` defined vs. `_FILE_OFFSET_BITS`
16// undefined in some Linux configurations.
17#undef _TIME_BITS
14#include "sanitizer_platform.h"18#include "sanitizer_platform.h"
15#if SANITIZER_SOLARIS19#if SANITIZER_SOLARIS
16# include <fcntl.h>20# include <fcntl.h>
lib/tsan/sanitizer_common/sanitizer_redefine_builtins.h+5-3
...@@ -17,9 +17,11 @@...@@ -17,9 +17,11 @@
17// The asm hack only works with GCC and Clang.17// The asm hack only works with GCC and Clang.
18# if !defined(_WIN32)18# if !defined(_WIN32)
1919
20asm("memcpy = __sanitizer_internal_memcpy");20asm(R"(
21asm("memmove = __sanitizer_internal_memmove");21 .set memcpy, __sanitizer_internal_memcpy
22asm("memset = __sanitizer_internal_memset");22 .set memmove, __sanitizer_internal_memmove
23 .set memset, __sanitizer_internal_memset
24 )");
2325
24# if defined(__cplusplus) && \26# if defined(__cplusplus) && \
25 !defined(SANITIZER_COMMON_REDEFINE_BUILTINS_IN_STD)27 !defined(SANITIZER_COMMON_REDEFINE_BUILTINS_IN_STD)
lib/tsan/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp+11-4
...@@ -137,10 +137,6 @@ class ThreadSuspender {...@@ -137,10 +137,6 @@ class ThreadSuspender {
137};137};
138138
139bool ThreadSuspender::SuspendThread(tid_t tid) {139bool ThreadSuspender::SuspendThread(tid_t tid) {
140 // Are we already attached to this thread?
141 // Currently this check takes linear time, however the number of threads is
142 // usually small.
143 if (suspended_threads_list_.ContainsTid(tid)) return false;
144 int pterrno;140 int pterrno;
145 if (internal_iserror(internal_ptrace(PTRACE_ATTACH, tid, nullptr, nullptr),141 if (internal_iserror(internal_ptrace(PTRACE_ATTACH, tid, nullptr, nullptr),
146 &pterrno)) {142 &pterrno)) {
...@@ -217,17 +213,28 @@ bool ThreadSuspender::SuspendAllThreads() {...@@ -217,17 +213,28 @@ bool ThreadSuspender::SuspendAllThreads() {
217 switch (thread_lister.ListThreads(&threads)) {213 switch (thread_lister.ListThreads(&threads)) {
218 case ThreadLister::Error:214 case ThreadLister::Error:
219 ResumeAllThreads();215 ResumeAllThreads();
216 VReport(1, "Failed to list threads\n");
220 return false;217 return false;
221 case ThreadLister::Incomplete:218 case ThreadLister::Incomplete:
219 VReport(1, "Incomplete list\n");
222 retry = true;220 retry = true;
223 break;221 break;
224 case ThreadLister::Ok:222 case ThreadLister::Ok:
225 break;223 break;
226 }224 }
227 for (tid_t tid : threads) {225 for (tid_t tid : threads) {
226 // Are we already attached to this thread?
227 // Currently this check takes linear time, however the number of threads
228 // is usually small.
229 if (suspended_threads_list_.ContainsTid(tid))
230 continue;
228 if (SuspendThread(tid))231 if (SuspendThread(tid))
229 retry = true;232 retry = true;
233 else
234 VReport(2, "%llu/status: %s\n", tid, thread_lister.LoadStatus(tid));
230 }235 }
236 if (retry)
237 VReport(1, "SuspendAllThreads retry: %d\n", i);
231 }238 }
232 return suspended_threads_list_.ThreadCount();239 return suspended_threads_list_.ThreadCount();
233}240}
lib/tsan/sanitizer_common/sanitizer_symbolizer.h+4-4
...@@ -185,17 +185,17 @@ class Symbolizer final {...@@ -185,17 +185,17 @@ class Symbolizer final {
185 class ModuleNameOwner {185 class ModuleNameOwner {
186 public:186 public:
187 explicit ModuleNameOwner(Mutex *synchronized_by)187 explicit ModuleNameOwner(Mutex *synchronized_by)
188 : last_match_(nullptr), mu_(synchronized_by) {188 : mu_(synchronized_by), last_match_(nullptr) {
189 storage_.reserve(kInitialCapacity);189 storage_.reserve(kInitialCapacity);
190 }190 }
191 const char *GetOwnedCopy(const char *str);191 const char *GetOwnedCopy(const char *str);
192192
193 private:193 private:
194 static const uptr kInitialCapacity = 1000;194 static const uptr kInitialCapacity = 1000;
195 InternalMmapVector<const char*> storage_;
196 const char *last_match_;
197195
198 Mutex *mu_;196 Mutex *mu_;
197 const char *last_match_ SANITIZER_GUARDED_BY(mu_);
198 InternalMmapVector<const char *> storage_ SANITIZER_GUARDED_BY(*mu_);
199 } module_names_;199 } module_names_;
200200
201 /// Platform-specific function for creating a Symbolizer object.201 /// Platform-specific function for creating a Symbolizer object.
...@@ -220,7 +220,7 @@ class Symbolizer final {...@@ -220,7 +220,7 @@ class Symbolizer final {
220 // always synchronized.220 // always synchronized.
221 Mutex mu_;221 Mutex mu_;
222222
223 IntrusiveList<SymbolizerTool> tools_;223 IntrusiveList<SymbolizerTool> tools_ SANITIZER_GUARDED_BY(mu_);
224224
225 explicit Symbolizer(IntrusiveList<SymbolizerTool> tools);225 explicit Symbolizer(IntrusiveList<SymbolizerTool> tools);
226226
lib/tsan/sanitizer_common/sanitizer_symbolizer_mac.cpp+2-2
...@@ -30,7 +30,7 @@ namespace __sanitizer {...@@ -30,7 +30,7 @@ namespace __sanitizer {
30bool DlAddrSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) {30bool DlAddrSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) {
31 Dl_info info;31 Dl_info info;
32 int result = dladdr((const void *)addr, &info);32 int result = dladdr((const void *)addr, &info);
33 if (!result) return false;33 if (!result || !info.dli_sname) return false;
3434
35 // Compute offset if possible. `dladdr()` doesn't always ensure that `addr >=35 // Compute offset if possible. `dladdr()` doesn't always ensure that `addr >=
36 // sym_addr` so only compute the offset when this holds. Failure to find the36 // sym_addr` so only compute the offset when this holds. Failure to find the
...@@ -51,7 +51,7 @@ bool DlAddrSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) {...@@ -51,7 +51,7 @@ bool DlAddrSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) {
51bool DlAddrSymbolizer::SymbolizeData(uptr addr, DataInfo *datainfo) {51bool DlAddrSymbolizer::SymbolizeData(uptr addr, DataInfo *datainfo) {
52 Dl_info info;52 Dl_info info;
53 int result = dladdr((const void *)addr, &info);53 int result = dladdr((const void *)addr, &info);
54 if (!result) return false;54 if (!result || !info.dli_sname) return false;
55 const char *demangled = DemangleSwiftAndCXX(info.dli_sname);55 const char *demangled = DemangleSwiftAndCXX(info.dli_sname);
56 if (!demangled)56 if (!demangled)
57 demangled = info.dli_sname;57 demangled = info.dli_sname;
lib/tsan/sanitizer_common/sanitizer_symbolizer_report.cpp+9-6
...@@ -227,12 +227,15 @@ static void ReportStackOverflowImpl(const SignalContext &sig, u32 tid,...@@ -227,12 +227,15 @@ static void ReportStackOverflowImpl(const SignalContext &sig, u32 tid,
227 SanitizerToolName, kDescription, (void *)sig.addr, (void *)sig.pc,227 SanitizerToolName, kDescription, (void *)sig.addr, (void *)sig.pc,
228 (void *)sig.bp, (void *)sig.sp, tid);228 (void *)sig.bp, (void *)sig.sp, tid);
229 Printf("%s", d.Default());229 Printf("%s", d.Default());
230 InternalMmapVector<BufferedStackTrace> stack_buffer(1);230 // Avoid SEGVs in the unwinder when bp couldn't be determined.
231 BufferedStackTrace *stack = stack_buffer.data();231 if (sig.bp) {
232 stack->Reset();232 InternalMmapVector<BufferedStackTrace> stack_buffer(1);
233 unwind(sig, unwind_context, stack);233 BufferedStackTrace *stack = stack_buffer.data();
234 stack->Print();234 stack->Reset();
235 ReportErrorSummary(kDescription, stack);235 unwind(sig, unwind_context, stack);
236 stack->Print();
237 ReportErrorSummary(kDescription, stack);
238 }
236}239}
237240
238static void ReportDeadlySignalImpl(const SignalContext &sig, u32 tid,241static void ReportDeadlySignalImpl(const SignalContext &sig, u32 tid,
lib/tsan/sanitizer_common/sanitizer_symbolizer_win.cpp+7-6
...@@ -65,12 +65,13 @@ void InitializeDbgHelpIfNeeded() {...@@ -65,12 +65,13 @@ void InitializeDbgHelpIfNeeded() {
65 HMODULE dbghelp = LoadLibraryA("dbghelp.dll");65 HMODULE dbghelp = LoadLibraryA("dbghelp.dll");
66 CHECK(dbghelp && "failed to load dbghelp.dll");66 CHECK(dbghelp && "failed to load dbghelp.dll");
6767
68#define DBGHELP_IMPORT(name) \68# define DBGHELP_IMPORT(name) \
69 do { \69 do { \
70 name = \70 name = reinterpret_cast<decltype(::name) *>( \
71 reinterpret_cast<decltype(::name) *>(GetProcAddress(dbghelp, #name)); \71 (void *)GetProcAddress(dbghelp, #name)); \
72 CHECK(name != nullptr); \72 CHECK(name != nullptr); \
73 } while (0)73 } while (0)
74
74 DBGHELP_IMPORT(StackWalk64);75 DBGHELP_IMPORT(StackWalk64);
75 DBGHELP_IMPORT(SymCleanup);76 DBGHELP_IMPORT(SymCleanup);
76 DBGHELP_IMPORT(SymFromAddr);77 DBGHELP_IMPORT(SymFromAddr);
lib/tsan/sanitizer_common/sanitizer_thread_history.cpp created+72
...@@ -0,0 +1,72 @@
1//===-- sanitizer_thread_history.cpp --------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "sanitizer_thread_history.h"
10
11#include "sanitizer_stackdepot.h"
12namespace __sanitizer {
13
14void PrintThreadHistory(ThreadRegistry &registry, InternalScopedString &out) {
15 ThreadRegistryLock l(&registry);
16 // Stack traces are largest part of printout and they often the same for
17 // multiple threads, so we will deduplicate them.
18 InternalMmapVector<const ThreadContextBase *> stacks;
19
20 registry.RunCallbackForEachThreadLocked(
21 [](ThreadContextBase *context, void *arg) {
22 static_cast<decltype(&stacks)>(arg)->push_back(context);
23 },
24 &stacks);
25
26 Sort(stacks.data(), stacks.size(),
27 [](const ThreadContextBase *a, const ThreadContextBase *b) {
28 if (a->stack_id < b->stack_id)
29 return true;
30 if (a->stack_id > b->stack_id)
31 return false;
32 return a->unique_id < b->unique_id;
33 });
34
35 auto describe_thread = [&](const ThreadContextBase *context) {
36 if (!context) {
37 out.Append("T-1");
38 return;
39 }
40 out.AppendF("T%llu/%llu", context->unique_id, context->os_id);
41 if (internal_strlen(context->name))
42 out.AppendF(" (%s)", context->name);
43 };
44
45 auto get_parent =
46 [&](const ThreadContextBase *context) -> const ThreadContextBase * {
47 if (!context)
48 return nullptr;
49 ThreadContextBase *parent = registry.GetThreadLocked(context->parent_tid);
50 if (!parent)
51 return nullptr;
52 if (parent->unique_id >= context->unique_id)
53 return nullptr;
54 return parent;
55 };
56
57 const ThreadContextBase *prev = nullptr;
58 for (const ThreadContextBase *context : stacks) {
59 if (prev && prev->stack_id != context->stack_id)
60 StackDepotGet(prev->stack_id).PrintTo(&out);
61 prev = context;
62 out.Append("Thread ");
63 describe_thread(context);
64 out.Append(" was created by ");
65 describe_thread(get_parent(context));
66 out.Append("\n");
67 }
68 if (prev)
69 StackDepotGet(prev->stack_id).PrintTo(&out);
70}
71
72} // namespace __sanitizer
lib/tsan/sanitizer_common/sanitizer_thread_history.h created+24
...@@ -0,0 +1,24 @@
1//===-- sanitizer_thread_history.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// Utility to print thread histroy from ThreadRegistry.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef SANITIZER_THREAD_HISTORY_H
14#define SANITIZER_THREAD_HISTORY_H
15
16#include "sanitizer_thread_registry.h"
17
18namespace __sanitizer {
19
20void PrintThreadHistory(ThreadRegistry& registry, InternalScopedString& out);
21
22} // namespace __sanitizer
23
24#endif // SANITIZER_THREAD_HISTORY_H
lib/tsan/sanitizer_common/sanitizer_thread_registry.cpp+33-18
...@@ -18,9 +18,17 @@...@@ -18,9 +18,17 @@
18namespace __sanitizer {18namespace __sanitizer {
1919
20ThreadContextBase::ThreadContextBase(u32 tid)20ThreadContextBase::ThreadContextBase(u32 tid)
21 : tid(tid), unique_id(0), reuse_count(), os_id(0), user_id(0),21 : tid(tid),
22 status(ThreadStatusInvalid), detached(false),22 unique_id(0),
23 thread_type(ThreadType::Regular), parent_tid(0), next(0) {23 reuse_count(),
24 os_id(0),
25 user_id(0),
26 status(ThreadStatusInvalid),
27 detached(false),
28 thread_type(ThreadType::Regular),
29 parent_tid(0),
30 stack_id(0),
31 next(0) {
24 name[0] = '\0';32 name[0] = '\0';
25 atomic_store(&thread_destroyed, 0, memory_order_release);33 atomic_store(&thread_destroyed, 0, memory_order_release);
26}34}
...@@ -39,8 +47,7 @@ void ThreadContextBase::SetName(const char *new_name) {...@@ -39,8 +47,7 @@ void ThreadContextBase::SetName(const char *new_name) {
39}47}
4048
41void ThreadContextBase::SetDead() {49void ThreadContextBase::SetDead() {
42 CHECK(status == ThreadStatusRunning ||50 CHECK(status == ThreadStatusRunning || status == ThreadStatusFinished);
43 status == ThreadStatusFinished);
44 status = ThreadStatusDead;51 status = ThreadStatusDead;
45 user_id = 0;52 user_id = 0;
46 OnDead();53 OnDead();
...@@ -68,7 +75,8 @@ void ThreadContextBase::SetFinished() {...@@ -68,7 +75,8 @@ void ThreadContextBase::SetFinished() {
68 // for a thread that never actually started. In that case the thread75 // for a thread that never actually started. In that case the thread
69 // should go to ThreadStatusFinished regardless of whether it was created76 // should go to ThreadStatusFinished regardless of whether it was created
70 // as detached.77 // as detached.
71 if (!detached || status == ThreadStatusCreated) status = ThreadStatusFinished;78 if (!detached || status == ThreadStatusCreated)
79 status = ThreadStatusFinished;
72 OnFinished();80 OnFinished();
73}81}
7482
...@@ -81,14 +89,17 @@ void ThreadContextBase::SetStarted(tid_t _os_id, ThreadType _thread_type,...@@ -81,14 +89,17 @@ void ThreadContextBase::SetStarted(tid_t _os_id, ThreadType _thread_type,
81}89}
8290
83void ThreadContextBase::SetCreated(uptr _user_id, u64 _unique_id,91void ThreadContextBase::SetCreated(uptr _user_id, u64 _unique_id,
84 bool _detached, u32 _parent_tid, void *arg) {92 bool _detached, u32 _parent_tid,
93 u32 _stack_tid, void *arg) {
85 status = ThreadStatusCreated;94 status = ThreadStatusCreated;
86 user_id = _user_id;95 user_id = _user_id;
87 unique_id = _unique_id;96 unique_id = _unique_id;
88 detached = _detached;97 detached = _detached;
89 // Parent tid makes no sense for the main thread.98 // Parent tid makes no sense for the main thread.
90 if (tid != kMainTid)99 if (tid != kMainTid) {
91 parent_tid = _parent_tid;100 parent_tid = _parent_tid;
101 stack_id = _stack_tid;
102 }
92 OnCreated(arg);103 OnCreated(arg);
93}104}
94105
...@@ -124,8 +135,10 @@ void ThreadRegistry::GetNumberOfThreads(uptr *total, uptr *running,...@@ -124,8 +135,10 @@ void ThreadRegistry::GetNumberOfThreads(uptr *total, uptr *running,
124 ThreadRegistryLock l(this);135 ThreadRegistryLock l(this);
125 if (total)136 if (total)
126 *total = threads_.size();137 *total = threads_.size();
127 if (running) *running = running_threads_;138 if (running)
128 if (alive) *alive = alive_threads_;139 *running = running_threads_;
140 if (alive)
141 *alive = alive_threads_;
129}142}
130143
131uptr ThreadRegistry::GetMaxAliveThreads() {144uptr ThreadRegistry::GetMaxAliveThreads() {
...@@ -134,7 +147,7 @@ uptr ThreadRegistry::GetMaxAliveThreads() {...@@ -134,7 +147,7 @@ uptr ThreadRegistry::GetMaxAliveThreads() {
134}147}
135148
136u32 ThreadRegistry::CreateThread(uptr user_id, bool detached, u32 parent_tid,149u32 ThreadRegistry::CreateThread(uptr user_id, bool detached, u32 parent_tid,
137 void *arg) {150 u32 stack_tid, void *arg) {
138 ThreadRegistryLock l(this);151 ThreadRegistryLock l(this);
139 u32 tid = kInvalidTid;152 u32 tid = kInvalidTid;
140 ThreadContextBase *tctx = QuarantinePop();153 ThreadContextBase *tctx = QuarantinePop();
...@@ -150,8 +163,10 @@ u32 ThreadRegistry::CreateThread(uptr user_id, bool detached, u32 parent_tid,...@@ -150,8 +163,10 @@ u32 ThreadRegistry::CreateThread(uptr user_id, bool detached, u32 parent_tid,
150 Report("%s: Thread limit (%u threads) exceeded. Dying.\n",163 Report("%s: Thread limit (%u threads) exceeded. Dying.\n",
151 SanitizerToolName, max_threads_);164 SanitizerToolName, max_threads_);
152#else165#else
153 Printf("race: limit on %u simultaneously alive goroutines is exceeded,"166 Printf(
154 " dying\n", max_threads_);167 "race: limit on %u simultaneously alive goroutines is exceeded,"
168 " dying\n",
169 max_threads_);
155#endif170#endif
156 Die();171 Die();
157 }172 }
...@@ -170,8 +185,8 @@ u32 ThreadRegistry::CreateThread(uptr user_id, bool detached, u32 parent_tid,...@@ -170,8 +185,8 @@ u32 ThreadRegistry::CreateThread(uptr user_id, bool detached, u32 parent_tid,
170 // positives later (e.g. if we join a wrong thread).185 // positives later (e.g. if we join a wrong thread).
171 CHECK(live_.try_emplace(user_id, tid).second);186 CHECK(live_.try_emplace(user_id, tid).second);
172 }187 }
173 tctx->SetCreated(user_id, total_threads_++, detached,188 tctx->SetCreated(user_id, total_threads_++, detached, parent_tid, stack_tid,
174 parent_tid, arg);189 arg);
175 return tid;190 return tid;
176}191}
177192
...@@ -196,8 +211,8 @@ u32 ThreadRegistry::FindThread(FindThreadCallback cb, void *arg) {...@@ -196,8 +211,8 @@ u32 ThreadRegistry::FindThread(FindThreadCallback cb, void *arg) {
196 return kInvalidTid;211 return kInvalidTid;
197}212}
198213
199ThreadContextBase *214ThreadContextBase *ThreadRegistry::FindThreadContextLocked(
200ThreadRegistry::FindThreadContextLocked(FindThreadCallback cb, void *arg) {215 FindThreadCallback cb, void *arg) {
201 CheckLocked();216 CheckLocked();
202 for (u32 tid = 0; tid < threads_.size(); tid++) {217 for (u32 tid = 0; tid < threads_.size(); tid++) {
203 ThreadContextBase *tctx = threads_[tid];218 ThreadContextBase *tctx = threads_[tid];
...@@ -210,7 +225,7 @@ ThreadRegistry::FindThreadContextLocked(FindThreadCallback cb, void *arg) {...@@ -210,7 +225,7 @@ ThreadRegistry::FindThreadContextLocked(FindThreadCallback cb, void *arg) {
210static bool FindThreadContextByOsIdCallback(ThreadContextBase *tctx,225static bool FindThreadContextByOsIdCallback(ThreadContextBase *tctx,
211 void *arg) {226 void *arg) {
212 return (tctx->os_id == (uptr)arg && tctx->status != ThreadStatusInvalid &&227 return (tctx->os_id == (uptr)arg && tctx->status != ThreadStatusInvalid &&
213 tctx->status != ThreadStatusDead);228 tctx->status != ThreadStatusDead);
214}229}
215230
216ThreadContextBase *ThreadRegistry::FindThreadContextByOsIDLocked(tid_t os_id) {231ThreadContextBase *ThreadRegistry::FindThreadContextByOsIDLocked(tid_t os_id) {
lib/tsan/sanitizer_common/sanitizer_thread_registry.h+8-3
...@@ -52,6 +52,7 @@ class ThreadContextBase {...@@ -52,6 +52,7 @@ class ThreadContextBase {
52 ThreadType thread_type;52 ThreadType thread_type;
5353
54 u32 parent_tid;54 u32 parent_tid;
55 u32 stack_id;
55 ThreadContextBase *next; // For storing thread contexts in a list.56 ThreadContextBase *next; // For storing thread contexts in a list.
5657
57 atomic_uint32_t thread_destroyed; // To address race of Joined vs Finished58 atomic_uint32_t thread_destroyed; // To address race of Joined vs Finished
...@@ -63,7 +64,7 @@ class ThreadContextBase {...@@ -63,7 +64,7 @@ class ThreadContextBase {
63 void SetFinished();64 void SetFinished();
64 void SetStarted(tid_t _os_id, ThreadType _thread_type, void *arg);65 void SetStarted(tid_t _os_id, ThreadType _thread_type, void *arg);
65 void SetCreated(uptr _user_id, u64 _unique_id, bool _detached,66 void SetCreated(uptr _user_id, u64 _unique_id, bool _detached,
66 u32 _parent_tid, void *arg);67 u32 _parent_tid, u32 _stack_tid, void *arg);
67 void Reset();68 void Reset();
6869
69 void SetDestroyed();70 void SetDestroyed();
...@@ -101,12 +102,16 @@ class SANITIZER_MUTEX ThreadRegistry {...@@ -101,12 +102,16 @@ class SANITIZER_MUTEX ThreadRegistry {
101102
102 // Should be guarded by ThreadRegistryLock.103 // Should be guarded by ThreadRegistryLock.
103 ThreadContextBase *GetThreadLocked(u32 tid) {104 ThreadContextBase *GetThreadLocked(u32 tid) {
104 return threads_.empty() ? nullptr : threads_[tid];105 return tid < threads_.size() ? threads_[tid] : nullptr;
105 }106 }
106107
107 u32 NumThreadsLocked() const { return threads_.size(); }108 u32 NumThreadsLocked() const { return threads_.size(); }
108109
109 u32 CreateThread(uptr user_id, bool detached, u32 parent_tid, void *arg);110 u32 CreateThread(uptr user_id, bool detached, u32 parent_tid, u32 stack_tid,
111 void *arg);
112 u32 CreateThread(uptr user_id, bool detached, u32 parent_tid, void *arg) {
113 return CreateThread(user_id, detached, parent_tid, 0, arg);
114 }
110115
111 typedef void (*ThreadCallback)(ThreadContextBase *tctx, void *arg);116 typedef void (*ThreadCallback)(ThreadContextBase *tctx, void *arg);
112 // Invokes callback with a specified arg for each thread context.117 // Invokes callback with a specified arg for each thread context.
lib/tsan/sanitizer_common/sanitizer_tls_get_addr.cpp+45-29
...@@ -14,6 +14,8 @@...@@ -14,6 +14,8 @@
1414
15#include "sanitizer_allocator_interface.h"15#include "sanitizer_allocator_interface.h"
16#include "sanitizer_atomic.h"16#include "sanitizer_atomic.h"
17#include "sanitizer_common/sanitizer_common.h"
18#include "sanitizer_common/sanitizer_internal_defs.h"
17#include "sanitizer_flags.h"19#include "sanitizer_flags.h"
18#include "sanitizer_platform_interceptors.h"20#include "sanitizer_platform_interceptors.h"
1921
...@@ -66,7 +68,7 @@ static DTLS::DTVBlock *DTLS_NextBlock(atomic_uintptr_t *cur) {...@@ -66,7 +68,7 @@ static DTLS::DTVBlock *DTLS_NextBlock(atomic_uintptr_t *cur) {
66}68}
6769
68static DTLS::DTV *DTLS_Find(uptr id) {70static DTLS::DTV *DTLS_Find(uptr id) {
69 VReport(2, "__tls_get_addr: DTLS_Find %p %zd\n", (void *)&dtls, id);71 VReport(3, "__tls_get_addr: DTLS_Find %p %zd\n", (void *)&dtls, id);
70 static constexpr uptr kPerBlock = ARRAY_SIZE(DTLS::DTVBlock::dtvs);72 static constexpr uptr kPerBlock = ARRAY_SIZE(DTLS::DTVBlock::dtvs);
71 DTLS::DTVBlock *cur = DTLS_NextBlock(&dtls.dtv_block);73 DTLS::DTVBlock *cur = DTLS_NextBlock(&dtls.dtv_block);
72 if (!cur)74 if (!cur)
...@@ -110,6 +112,21 @@ SANITIZER_WEAK_ATTRIBUTE...@@ -110,6 +112,21 @@ SANITIZER_WEAK_ATTRIBUTE
110const void *__sanitizer_get_allocated_begin(const void *p);112const void *__sanitizer_get_allocated_begin(const void *p);
111}113}
112114
115SANITIZER_INTERFACE_WEAK_DEF(uptr, __sanitizer_get_dtls_size,
116 const void *tls_begin) {
117 const void *start = __sanitizer_get_allocated_begin(tls_begin);
118 if (!start)
119 return 0;
120 CHECK_LE(start, tls_begin);
121 uptr tls_size = __sanitizer_get_allocated_size(start);
122 VReport(2, "__tls_get_addr: glibc DTLS suspected; tls={%p,0x%zx}\n",
123 tls_begin, tls_size);
124 uptr offset =
125 (reinterpret_cast<uptr>(tls_begin) - reinterpret_cast<uptr>(start));
126 CHECK_LE(offset, tls_size);
127 return tls_size - offset;
128}
129
113DTLS::DTV *DTLS_on_tls_get_addr(void *arg_void, void *res,130DTLS::DTV *DTLS_on_tls_get_addr(void *arg_void, void *res,
114 uptr static_tls_begin, uptr static_tls_end) {131 uptr static_tls_begin, uptr static_tls_end) {
115 if (!common_flags()->intercept_tls_get_addr) return 0;132 if (!common_flags()->intercept_tls_get_addr) return 0;
...@@ -117,8 +134,8 @@ DTLS::DTV *DTLS_on_tls_get_addr(void *arg_void, void *res,...@@ -117,8 +134,8 @@ DTLS::DTV *DTLS_on_tls_get_addr(void *arg_void, void *res,
117 uptr dso_id = arg->dso_id;134 uptr dso_id = arg->dso_id;
118 DTLS::DTV *dtv = DTLS_Find(dso_id);135 DTLS::DTV *dtv = DTLS_Find(dso_id);
119 if (!dtv || dtv->beg)136 if (!dtv || dtv->beg)
120 return 0;137 return nullptr;
121 uptr tls_size = 0;138 CHECK_LE(static_tls_begin, static_tls_end);
122 uptr tls_beg = reinterpret_cast<uptr>(res) - arg->offset - kDtvOffset;139 uptr tls_beg = reinterpret_cast<uptr>(res) - arg->offset - kDtvOffset;
123 VReport(2,140 VReport(2,
124 "__tls_get_addr: %p {0x%zx,0x%zx} => %p; tls_beg: %p; sp: %p "141 "__tls_get_addr: %p {0x%zx,0x%zx} => %p; tls_beg: %p; sp: %p "
...@@ -126,36 +143,33 @@ DTLS::DTV *DTLS_on_tls_get_addr(void *arg_void, void *res,...@@ -126,36 +143,33 @@ DTLS::DTV *DTLS_on_tls_get_addr(void *arg_void, void *res,
126 (void *)arg, arg->dso_id, arg->offset, res, (void *)tls_beg,143 (void *)arg, arg->dso_id, arg->offset, res, (void *)tls_beg,
127 (void *)&tls_beg,144 (void *)&tls_beg,
128 atomic_load(&number_of_live_dtls, memory_order_relaxed));145 atomic_load(&number_of_live_dtls, memory_order_relaxed));
129 if (dtls.last_memalign_ptr == tls_beg) {146 if (tls_beg >= static_tls_begin && tls_beg < static_tls_end) {
130 tls_size = dtls.last_memalign_size;
131 VReport(2, "__tls_get_addr: glibc <=2.24 suspected; tls={%p,0x%zx}\n",
132 (void *)tls_beg, tls_size);
133 } else if (tls_beg >= static_tls_begin && tls_beg < static_tls_end) {
134 // This is the static TLS block which was initialized / unpoisoned at thread147 // This is the static TLS block which was initialized / unpoisoned at thread
135 // creation.148 // creation.
136 VReport(2, "__tls_get_addr: static tls: %p\n", (void *)tls_beg);149 VReport(2, "__tls_get_addr: static tls: %p\n", (void *)tls_beg);
137 tls_size = 0;150 dtv->beg = tls_beg;
138 } else if (const void *start =151 dtv->size = 0;
139 __sanitizer_get_allocated_begin((void *)tls_beg)) {152 return nullptr;
140 tls_beg = (uptr)start;
141 tls_size = __sanitizer_get_allocated_size(start);
142 VReport(2, "__tls_get_addr: glibc >=2.25 suspected; tls={%p,0x%zx}\n",
143 (void *)tls_beg, tls_size);
144 } else {
145 VReport(2, "__tls_get_addr: Can't guess glibc version\n");
146 // This may happen inside the DTOR of main thread, so just ignore it.
147 tls_size = 0;
148 }153 }
154 if (uptr tls_size =
155 __sanitizer_get_dtls_size(reinterpret_cast<void *>(tls_beg))) {
156 dtv->beg = tls_beg;
157 dtv->size = tls_size;
158 return dtv;
159 }
160 VReport(2, "__tls_get_addr: Can't guess glibc version\n");
161 // This may happen inside the DTOR a thread, or async signal handlers before
162 // thread initialization, so just ignore it.
163 //
164 // If the unknown block is dynamic TLS, unlikely we will be able to recognize
165 // it in future, mark it as done with '{tls_beg, 0}'.
166 //
167 // If the block is static TLS, possible reason of failed detection is nullptr
168 // in `static_tls_begin`. Regardless of reasons, the future handling of static
169 // TLS is still '{tls_beg, 0}'.
149 dtv->beg = tls_beg;170 dtv->beg = tls_beg;
150 dtv->size = tls_size;171 dtv->size = 0;
151 return dtv;172 return nullptr;
152}
153
154void DTLS_on_libc_memalign(void *ptr, uptr size) {
155 if (!common_flags()->intercept_tls_get_addr) return;
156 VReport(2, "DTLS_on_libc_memalign: %p 0x%zx\n", ptr, size);
157 dtls.last_memalign_ptr = reinterpret_cast<uptr>(ptr);
158 dtls.last_memalign_size = size;
159}173}
160174
161DTLS *DTLS_Get() { return &dtls; }175DTLS *DTLS_Get() { return &dtls; }
...@@ -166,7 +180,9 @@ bool DTLSInDestruction(DTLS *dtls) {...@@ -166,7 +180,9 @@ bool DTLSInDestruction(DTLS *dtls) {
166}180}
167181
168#else182#else
169void DTLS_on_libc_memalign(void *ptr, uptr size) {}183SANITIZER_INTERFACE_WEAK_DEF(uptr, __sanitizer_get_dtls_size, const void *) {
184 return 0;
185}
170DTLS::DTV *DTLS_on_tls_get_addr(void *arg, void *res,186DTLS::DTV *DTLS_on_tls_get_addr(void *arg, void *res,
171 unsigned long, unsigned long) { return 0; }187 unsigned long, unsigned long) { return 0; }
172DTLS *DTLS_Get() { return 0; }188DTLS *DTLS_Get() { return 0; }
lib/tsan/sanitizer_common/sanitizer_tls_get_addr.h-4
...@@ -55,10 +55,6 @@ struct DTLS {...@@ -55,10 +55,6 @@ struct DTLS {
55 static_assert(sizeof(DTVBlock) <= 4096UL, "Unexpected block size");55 static_assert(sizeof(DTVBlock) <= 4096UL, "Unexpected block size");
5656
57 atomic_uintptr_t dtv_block;57 atomic_uintptr_t dtv_block;
58
59 // Auxiliary fields, don't access them outside sanitizer_tls_get_addr.cpp
60 uptr last_memalign_size;
61 uptr last_memalign_ptr;
62};58};
6359
64template <typename Fn>60template <typename Fn>
lib/tsan/sanitizer_common/sanitizer_win.cpp+81-20
...@@ -164,7 +164,24 @@ void UnmapOrDie(void *addr, uptr size, bool raw_report) {...@@ -164,7 +164,24 @@ void UnmapOrDie(void *addr, uptr size, bool raw_report) {
164static void *ReturnNullptrOnOOMOrDie(uptr size, const char *mem_type,164static void *ReturnNullptrOnOOMOrDie(uptr size, const char *mem_type,
165 const char *mmap_type) {165 const char *mmap_type) {
166 error_t last_error = GetLastError();166 error_t last_error = GetLastError();
167 if (last_error == ERROR_NOT_ENOUGH_MEMORY)167
168 // Assumption: VirtualAlloc is the last system call that was invoked before
169 // this method.
170 // VirtualAlloc emits one of 3 error codes when running out of memory
171 // 1. ERROR_NOT_ENOUGH_MEMORY:
172 // There's not enough memory to execute the command
173 // 2. ERROR_INVALID_PARAMETER:
174 // VirtualAlloc will return this if the request would allocate memory at an
175 // address exceeding or being very close to the maximum application address
176 // (the `lpMaximumApplicationAddress` field within the `SystemInfo` struct).
177 // This does not seem to be officially documented, but is corroborated here:
178 // https://stackoverflow.com/questions/45833674/why-does-virtualalloc-fail-for-lpaddress-greater-than-0x6ffffffffff
179 // 3. ERROR_COMMITMENT_LIMIT:
180 // VirtualAlloc will return this if e.g. the pagefile is too small to commit
181 // the requested amount of memory.
182 if (last_error == ERROR_NOT_ENOUGH_MEMORY ||
183 last_error == ERROR_INVALID_PARAMETER ||
184 last_error == ERROR_COMMITMENT_LIMIT)
168 return nullptr;185 return nullptr;
169 ReportMmapFailureAndDie(size, mem_type, mmap_type, last_error);186 ReportMmapFailureAndDie(size, mem_type, mmap_type, last_error);
170}187}
...@@ -873,24 +890,18 @@ uptr GetTlsSize() {...@@ -873,24 +890,18 @@ uptr GetTlsSize() {
873 return 0;890 return 0;
874}891}
875892
876void InitTlsSize() {893void GetThreadStackAndTls(bool main, uptr *stk_begin, uptr *stk_end,
877}894 uptr *tls_begin, uptr *tls_end) {
878895# if SANITIZER_GO
879void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,896 *stk_begin = 0;
880 uptr *tls_addr, uptr *tls_size) {897 *stk_end = 0;
881#if SANITIZER_GO898 *tls_begin = 0;
882 *stk_addr = 0;899 *tls_end = 0;
883 *stk_size = 0;900# else
884 *tls_addr = 0;901 GetThreadStackTopAndBottom(main, stk_end, stk_begin);
885 *tls_size = 0;902 *tls_begin = 0;
886#else903 *tls_end = 0;
887 uptr stack_top, stack_bottom;904# endif
888 GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
889 *stk_addr = stack_bottom;
890 *stk_size = stack_top - stack_bottom;
891 *tls_addr = 0;
892 *tls_size = 0;
893#endif
894}905}
895906
896void ReportFile::Write(const char *buffer, uptr length) {907void ReportFile::Write(const char *buffer, uptr length) {
...@@ -974,6 +985,11 @@ bool IsAccessibleMemoryRange(uptr beg, uptr size) {...@@ -974,6 +985,11 @@ bool IsAccessibleMemoryRange(uptr beg, uptr size) {
974 return true;985 return true;
975}986}
976987
988bool TryMemCpy(void *dest, const void *src, uptr n) {
989 // TODO: implement.
990 return false;
991}
992
977bool SignalContext::IsStackOverflow() const {993bool SignalContext::IsStackOverflow() const {
978 return (DWORD)GetType() == EXCEPTION_STACK_OVERFLOW;994 return (DWORD)GetType() == EXCEPTION_STACK_OVERFLOW;
979}995}
...@@ -1039,7 +1055,52 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {...@@ -1039,7 +1055,52 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
1039}1055}
10401056
1041void SignalContext::DumpAllRegisters(void *context) {1057void SignalContext::DumpAllRegisters(void *context) {
1042 // FIXME: Implement this.1058 CONTEXT *ctx = (CONTEXT *)context;
1059# if defined(_M_X64)
1060 Report("Register values:\n");
1061 Printf("rax = %llx ", ctx->Rax);
1062 Printf("rbx = %llx ", ctx->Rbx);
1063 Printf("rcx = %llx ", ctx->Rcx);
1064 Printf("rdx = %llx ", ctx->Rdx);
1065 Printf("\n");
1066 Printf("rdi = %llx ", ctx->Rdi);
1067 Printf("rsi = %llx ", ctx->Rsi);
1068 Printf("rbp = %llx ", ctx->Rbp);
1069 Printf("rsp = %llx ", ctx->Rsp);
1070 Printf("\n");
1071 Printf("r8 = %llx ", ctx->R8);
1072 Printf("r9 = %llx ", ctx->R9);
1073 Printf("r10 = %llx ", ctx->R10);
1074 Printf("r11 = %llx ", ctx->R11);
1075 Printf("\n");
1076 Printf("r12 = %llx ", ctx->R12);
1077 Printf("r13 = %llx ", ctx->R13);
1078 Printf("r14 = %llx ", ctx->R14);
1079 Printf("r15 = %llx ", ctx->R15);
1080 Printf("\n");
1081# elif defined(_M_IX86)
1082 Report("Register values:\n");
1083 Printf("eax = %lx ", ctx->Eax);
1084 Printf("ebx = %lx ", ctx->Ebx);
1085 Printf("ecx = %lx ", ctx->Ecx);
1086 Printf("edx = %lx ", ctx->Edx);
1087 Printf("\n");
1088 Printf("edi = %lx ", ctx->Edi);
1089 Printf("esi = %lx ", ctx->Esi);
1090 Printf("ebp = %lx ", ctx->Ebp);
1091 Printf("esp = %lx ", ctx->Esp);
1092 Printf("\n");
1093# elif defined(_M_ARM64)
1094 Report("Register values:\n");
1095 for (int i = 0; i <= 30; i++) {
1096 Printf("x%d%s = %llx", i < 10 ? " " : "", ctx->X[i]);
1097 if (i % 4 == 3)
1098 Printf("\n");
1099 }
1100# else
1101 // TODO
1102 (void)ctx;
1103# endif
1043}1104}
10441105
1045int SignalContext::GetType() const {1106int SignalContext::GetType() const {
lib/tsan/sanitizer_common/sanitizer_win_dll_thunk.cpp deleted-101
...@@ -1,101 +0,0 @@
1//===-- sanitizer_win_dll_thunk.cpp ---------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8// This file defines a family of thunks that should be statically linked into
9// the DLLs that have instrumentation in order to delegate the calls to the
10// shared runtime that lives in the main binary.
11// See https://github.com/google/sanitizers/issues/209 for the details.
12//===----------------------------------------------------------------------===//
13
14#ifdef SANITIZER_DLL_THUNK
15#include "sanitizer_win_defs.h"
16#include "sanitizer_win_dll_thunk.h"
17#include "interception/interception.h"
18
19extern "C" {
20void *WINAPI GetModuleHandleA(const char *module_name);
21void abort();
22}
23
24namespace __sanitizer {
25uptr dllThunkGetRealAddrOrDie(const char *name) {
26 uptr ret =
27 __interception::InternalGetProcAddress((void *)GetModuleHandleA(0), name);
28 if (!ret)
29 abort();
30 return ret;
31}
32
33int dllThunkIntercept(const char* main_function, uptr dll_function) {
34 uptr wrapper = dllThunkGetRealAddrOrDie(main_function);
35 if (!__interception::OverrideFunction(dll_function, wrapper, 0))
36 abort();
37 return 0;
38}
39
40int dllThunkInterceptWhenPossible(const char* main_function,
41 const char* default_function, uptr dll_function) {
42 uptr wrapper = __interception::InternalGetProcAddress(
43 (void *)GetModuleHandleA(0), main_function);
44 if (!wrapper)
45 wrapper = dllThunkGetRealAddrOrDie(default_function);
46 if (!__interception::OverrideFunction(dll_function, wrapper, 0))
47 abort();
48 return 0;
49}
50} // namespace __sanitizer
51
52// Include Sanitizer Common interface.
53#define INTERFACE_FUNCTION(Name) INTERCEPT_SANITIZER_FUNCTION(Name)
54#define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name)
55#include "sanitizer_common_interface.inc"
56
57#pragma section(".DLLTH$A", read)
58#pragma section(".DLLTH$Z", read)
59
60typedef void (*DllThunkCB)();
61extern "C" {
62__declspec(allocate(".DLLTH$A")) DllThunkCB __start_dll_thunk;
63__declspec(allocate(".DLLTH$Z")) DllThunkCB __stop_dll_thunk;
64}
65
66// Disable compiler warnings that show up if we declare our own version
67// of a compiler intrinsic (e.g. strlen).
68#pragma warning(disable: 4391)
69#pragma warning(disable: 4392)
70
71extern "C" int __dll_thunk_init() {
72 static bool flag = false;
73 // __dll_thunk_init is expected to be called by only one thread.
74 if (flag) return 0;
75 flag = true;
76
77 for (DllThunkCB *it = &__start_dll_thunk; it < &__stop_dll_thunk; ++it)
78 if (*it)
79 (*it)();
80
81 // In DLLs, the callbacks are expected to return 0,
82 // otherwise CRT initialization fails.
83 return 0;
84}
85
86// We want to call dll_thunk_init before C/C++ initializers / constructors are
87// executed, otherwise functions like memset might be invoked.
88#pragma section(".CRT$XIB", long, read)
89__declspec(allocate(".CRT$XIB")) int (*__dll_thunk_preinit)() =
90 __dll_thunk_init;
91
92static void WINAPI dll_thunk_thread_init(void *mod, unsigned long reason,
93 void *reserved) {
94 if (reason == /*DLL_PROCESS_ATTACH=*/1) __dll_thunk_init();
95}
96
97#pragma section(".CRT$XLAB", long, read)
98__declspec(allocate(".CRT$XLAB")) void (WINAPI *__dll_thunk_tls_init)(void *,
99 unsigned long, void *) = dll_thunk_thread_init;
100
101#endif // SANITIZER_DLL_THUNK
lib/tsan/sanitizer_common/sanitizer_win_dll_thunk.h deleted-181
...@@ -1,181 +0,0 @@
1//===-- sanitizer_win_dll_thunk.h -----------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8// This header provide helper macros to delegate calls to the shared runtime
9// that lives in the main executable. It should be included to dll_thunks that
10// will be linked to the dlls, when the sanitizer is a static library included
11// in the main executable.
12//===----------------------------------------------------------------------===//
13#ifndef SANITIZER_WIN_DLL_THUNK_H
14#define SANITIZER_WIN_DLL_THUNK_H
15#include "sanitizer_internal_defs.h"
16
17namespace __sanitizer {
18uptr dllThunkGetRealAddrOrDie(const char *name);
19
20int dllThunkIntercept(const char* main_function, uptr dll_function);
21
22int dllThunkInterceptWhenPossible(const char* main_function,
23 const char* default_function, uptr dll_function);
24}
25
26extern "C" int __dll_thunk_init();
27
28// ----------------- Function interception helper macros -------------------- //
29// Override dll_function with main_function from main executable.
30#define INTERCEPT_OR_DIE(main_function, dll_function) \
31 static int intercept_##dll_function() { \
32 return __sanitizer::dllThunkIntercept(main_function, (__sanitizer::uptr) \
33 dll_function); \
34 } \
35 __pragma(section(".DLLTH$M", long, read)) \
36 __declspec(allocate(".DLLTH$M")) int (*__dll_thunk_##dll_function)() = \
37 intercept_##dll_function;
38
39// Try to override dll_function with main_function from main executable.
40// If main_function is not present, override dll_function with default_function.
41#define INTERCEPT_WHEN_POSSIBLE(main_function, default_function, dll_function) \
42 static int intercept_##dll_function() { \
43 return __sanitizer::dllThunkInterceptWhenPossible(main_function, \
44 default_function, (__sanitizer::uptr)dll_function); \
45 } \
46 __pragma(section(".DLLTH$M", long, read)) \
47 __declspec(allocate(".DLLTH$M")) int (*__dll_thunk_##dll_function)() = \
48 intercept_##dll_function;
49
50// -------------------- Function interception macros ------------------------ //
51// Special case of hooks -- ASan own interface functions. Those are only called
52// after __asan_init, thus an empty implementation is sufficient.
53#define INTERCEPT_SANITIZER_FUNCTION(name) \
54 extern "C" __declspec(noinline) void name() { \
55 volatile int prevent_icf = (__LINE__ << 8) ^ __COUNTER__; \
56 static const char function_name[] = #name; \
57 for (const char* ptr = &function_name[0]; *ptr; ++ptr) \
58 prevent_icf ^= *ptr; \
59 (void)prevent_icf; \
60 __debugbreak(); \
61 } \
62 INTERCEPT_OR_DIE(#name, name)
63
64// Special case of hooks -- Weak functions, could be redefined in the main
65// executable, but that is not necessary, so we shouldn't die if we can not find
66// a reference. Instead, when the function is not present in the main executable
67// we consider the default impl provided by asan library.
68#define INTERCEPT_SANITIZER_WEAK_FUNCTION(name) \
69 extern "C" __declspec(noinline) void name() { \
70 volatile int prevent_icf = (__LINE__ << 8) ^ __COUNTER__; \
71 static const char function_name[] = #name; \
72 for (const char* ptr = &function_name[0]; *ptr; ++ptr) \
73 prevent_icf ^= *ptr; \
74 (void)prevent_icf; \
75 __debugbreak(); \
76 } \
77 INTERCEPT_WHEN_POSSIBLE(#name, STRINGIFY(WEAK_EXPORT_NAME(name)), name)
78
79// We can't define our own version of strlen etc. because that would lead to
80// link-time or even type mismatch errors. Instead, we can declare a function
81// just to be able to get its address. Me may miss the first few calls to the
82// functions since it can be called before __dll_thunk_init, but that would lead
83// to false negatives in the startup code before user's global initializers,
84// which isn't a big deal.
85#define INTERCEPT_LIBRARY_FUNCTION(name) \
86 extern "C" void name(); \
87 INTERCEPT_OR_DIE(STRINGIFY(WRAP(name)), name)
88
89// Use these macros for functions that could be called before __dll_thunk_init()
90// is executed and don't lead to errors if defined (free, malloc, etc).
91#define INTERCEPT_WRAP_V_V(name) \
92 extern "C" void name() { \
93 typedef decltype(name) *fntype; \
94 static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \
95 fn(); \
96 } \
97 INTERCEPT_OR_DIE(#name, name);
98
99#define INTERCEPT_WRAP_V_W(name) \
100 extern "C" void name(void *arg) { \
101 typedef decltype(name) *fntype; \
102 static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \
103 fn(arg); \
104 } \
105 INTERCEPT_OR_DIE(#name, name);
106
107#define INTERCEPT_WRAP_V_WW(name) \
108 extern "C" void name(void *arg1, void *arg2) { \
109 typedef decltype(name) *fntype; \
110 static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \
111 fn(arg1, arg2); \
112 } \
113 INTERCEPT_OR_DIE(#name, name);
114
115#define INTERCEPT_WRAP_V_WWW(name) \
116 extern "C" void name(void *arg1, void *arg2, void *arg3) { \
117 typedef decltype(name) *fntype; \
118 static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \
119 fn(arg1, arg2, arg3); \
120 } \
121 INTERCEPT_OR_DIE(#name, name);
122
123#define INTERCEPT_WRAP_W_V(name) \
124 extern "C" void *name() { \
125 typedef decltype(name) *fntype; \
126 static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \
127 return fn(); \
128 } \
129 INTERCEPT_OR_DIE(#name, name);
130
131#define INTERCEPT_WRAP_W_W(name) \
132 extern "C" void *name(void *arg) { \
133 typedef decltype(name) *fntype; \
134 static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \
135 return fn(arg); \
136 } \
137 INTERCEPT_OR_DIE(#name, name);
138
139#define INTERCEPT_WRAP_W_WW(name) \
140 extern "C" void *name(void *arg1, void *arg2) { \
141 typedef decltype(name) *fntype; \
142 static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \
143 return fn(arg1, arg2); \
144 } \
145 INTERCEPT_OR_DIE(#name, name);
146
147#define INTERCEPT_WRAP_W_WWW(name) \
148 extern "C" void *name(void *arg1, void *arg2, void *arg3) { \
149 typedef decltype(name) *fntype; \
150 static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \
151 return fn(arg1, arg2, arg3); \
152 } \
153 INTERCEPT_OR_DIE(#name, name);
154
155#define INTERCEPT_WRAP_W_WWWW(name) \
156 extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4) { \
157 typedef decltype(name) *fntype; \
158 static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \
159 return fn(arg1, arg2, arg3, arg4); \
160 } \
161 INTERCEPT_OR_DIE(#name, name);
162
163#define INTERCEPT_WRAP_W_WWWWW(name) \
164 extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4, \
165 void *arg5) { \
166 typedef decltype(name) *fntype; \
167 static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \
168 return fn(arg1, arg2, arg3, arg4, arg5); \
169 } \
170 INTERCEPT_OR_DIE(#name, name);
171
172#define INTERCEPT_WRAP_W_WWWWWW(name) \
173 extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4, \
174 void *arg5, void *arg6) { \
175 typedef decltype(name) *fntype; \
176 static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \
177 return fn(arg1, arg2, arg3, arg4, arg5, arg6); \
178 } \
179 INTERCEPT_OR_DIE(#name, name);
180
181#endif // SANITIZER_WIN_DLL_THUNK_H
lib/tsan/sanitizer_common/sanitizer_win_dynamic_runtime_thunk.cpp deleted-26
...@@ -1,26 +0,0 @@
1//===-- santizer_win_dynamic_runtime_thunk.cpp ----------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines things that need to be present in the application modules
10// to interact with Sanitizer Common, when it is included in a dll.
11//
12//===----------------------------------------------------------------------===//
13#ifdef SANITIZER_DYNAMIC_RUNTIME_THUNK
14#define SANITIZER_IMPORT_INTERFACE 1
15#include "sanitizer_win_defs.h"
16// Define weak alias for all weak functions imported from sanitizer common.
17#define INTERFACE_FUNCTION(Name)
18#define INTERFACE_WEAK_FUNCTION(Name) WIN_WEAK_IMPORT_DEF(Name)
19#include "sanitizer_common_interface.inc"
20#endif // SANITIZER_DYNAMIC_RUNTIME_THUNK
21
22namespace __sanitizer {
23// Add one, otherwise unused, external symbol to this object file so that the
24// Visual C++ linker includes it and reads the .drective section.
25void ForceWholeArchiveIncludeForSanitizerCommon() {}
26}
lib/tsan/sanitizer_common/sanitizer_win_immortalize.h created+71
...@@ -0,0 +1,71 @@
1//===-- sanitizer_win_immortalize.h ---------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file is shared between AddressSanitizer, and interception.
10//
11// Windows-specific thread-safe and pre-CRT global initialization safe
12// infrastructure to create an object whose destructor is never called.
13//===----------------------------------------------------------------------===//
14#if SANITIZER_WINDOWS
15# pragma once
16// Requires including sanitizer_placement_new.h (which is not allowed to be
17// included in headers).
18
19# include "sanitizer_win_defs.h"
20// These types are required to satisfy XFG which requires that the names of the
21// types for indirect calls to be correct as well as the name of the original
22// type for any typedefs.
23
24// TODO: There must be a better way to do this
25# ifndef _WINDOWS_
26typedef void* PVOID;
27typedef int BOOL;
28typedef union _RTL_RUN_ONCE {
29 PVOID ptr;
30} INIT_ONCE, *PINIT_ONCE;
31
32extern "C" {
33__declspec(dllimport) int WINAPI InitOnceExecuteOnce(
34 PINIT_ONCE, BOOL(WINAPI*)(PINIT_ONCE, PVOID, PVOID*), void*, void*);
35}
36# endif
37
38namespace __sanitizer {
39template <class Ty>
40BOOL WINAPI immortalize_impl(PINIT_ONCE, PVOID storage_ptr, PVOID*) noexcept {
41 // Ty must provide a placement new operator
42 new (storage_ptr) Ty();
43 return 1;
44}
45
46template <class Ty, typename Arg>
47BOOL WINAPI immortalize_impl(PINIT_ONCE, PVOID storage_ptr,
48 PVOID* param) noexcept {
49 // Ty must provide a placement new operator
50 new (storage_ptr) Ty(*((Arg*)param));
51 return 1;
52}
53
54template <class Ty>
55Ty& immortalize() { // return a reference to an object that will live forever
56 static INIT_ONCE flag;
57 alignas(Ty) static unsigned char storage[sizeof(Ty)];
58 InitOnceExecuteOnce(&flag, immortalize_impl<Ty>, &storage, nullptr);
59 return reinterpret_cast<Ty&>(storage);
60}
61
62template <class Ty, typename Arg>
63Ty& immortalize(
64 Arg arg) { // return a reference to an object that will live forever
65 static INIT_ONCE flag;
66 alignas(Ty) static unsigned char storage[sizeof(Ty)];
67 InitOnceExecuteOnce(&flag, immortalize_impl<Ty, Arg>, &storage, &arg);
68 return reinterpret_cast<Ty&>(storage);
69}
70} // namespace __sanitizer
71#endif // SANITIZER_WINDOWS
lib/tsan/sanitizer_common/sanitizer_win_interception.cpp created+156
...@@ -0,0 +1,156 @@
1//===-- sanitizer_win_interception.cpp -------------------- --*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Windows-specific export surface to provide interception for parts of the
10// runtime that are always statically linked, both for overriding user-defined
11// functions as well as registering weak functions that the ASAN runtime should
12// use over defaults.
13//
14//===----------------------------------------------------------------------===//
15
16#include "sanitizer_platform.h"
17#if SANITIZER_WINDOWS
18# include <stddef.h>
19
20# include "interception/interception.h"
21# include "sanitizer_addrhashmap.h"
22# include "sanitizer_common.h"
23# include "sanitizer_internal_defs.h"
24# include "sanitizer_placement_new.h"
25# include "sanitizer_win_immortalize.h"
26# include "sanitizer_win_interception.h"
27
28using namespace __sanitizer;
29
30extern "C" void *__ImageBase;
31
32namespace __sanitizer {
33
34static uptr GetSanitizerDllExport(const char *export_name) {
35 const uptr function_address =
36 __interception::InternalGetProcAddress(&__ImageBase, export_name);
37 if (function_address == 0) {
38 Report("ERROR: Failed to find sanitizer DLL export '%s'\n", export_name);
39 CHECK("Failed to find sanitizer DLL export" && 0);
40 }
41 return function_address;
42}
43
44struct WeakCallbackList {
45 explicit constexpr WeakCallbackList(RegisterWeakFunctionCallback cb)
46 : callback(cb), next(nullptr) {}
47
48 static void *operator new(size_t size) { return InternalAlloc(size); }
49
50 static void operator delete(void *p) { InternalFree(p); }
51
52 RegisterWeakFunctionCallback callback;
53 WeakCallbackList *next;
54};
55using WeakCallbackMap = AddrHashMap<WeakCallbackList *, 11>;
56
57static WeakCallbackMap *GetWeakCallbackMap() {
58 return &immortalize<WeakCallbackMap>();
59}
60
61void AddRegisterWeakFunctionCallback(uptr export_address,
62 RegisterWeakFunctionCallback cb) {
63 WeakCallbackMap::Handle h_find_or_create(GetWeakCallbackMap(), export_address,
64 false, true);
65 CHECK(h_find_or_create.exists());
66 if (h_find_or_create.created()) {
67 *h_find_or_create = new WeakCallbackList(cb);
68 } else {
69 (*h_find_or_create)->next = new WeakCallbackList(cb);
70 }
71}
72
73static void RunWeakFunctionCallbacks(uptr export_address) {
74 WeakCallbackMap::Handle h_find(GetWeakCallbackMap(), export_address, false,
75 false);
76 if (!h_find.exists()) {
77 return;
78 }
79
80 WeakCallbackList *list = *h_find;
81 do {
82 list->callback();
83 } while ((list = list->next));
84}
85
86} // namespace __sanitizer
87
88extern "C" __declspec(dllexport) bool __cdecl __sanitizer_override_function(
89 const char *export_name, const uptr user_function,
90 uptr *const old_user_function) {
91 CHECK(export_name);
92 CHECK(user_function);
93
94 const uptr sanitizer_function = GetSanitizerDllExport(export_name);
95
96 const bool function_overridden = __interception::OverrideFunction(
97 user_function, sanitizer_function, old_user_function);
98 if (!function_overridden) {
99 Report(
100 "ERROR: Failed to override local function at '%p' with sanitizer "
101 "function '%s'\n",
102 user_function, export_name);
103 CHECK("Failed to replace local function with sanitizer version." && 0);
104 }
105
106 return function_overridden;
107}
108
109extern "C"
110 __declspec(dllexport) bool __cdecl __sanitizer_override_function_by_addr(
111 const uptr source_function, const uptr target_function,
112 uptr *const old_target_function) {
113 CHECK(source_function);
114 CHECK(target_function);
115
116 const bool function_overridden = __interception::OverrideFunction(
117 target_function, source_function, old_target_function);
118 if (!function_overridden) {
119 Report(
120 "ERROR: Failed to override function at '%p' with function at "
121 "'%p'\n",
122 target_function, source_function);
123 CHECK("Failed to apply function override." && 0);
124 }
125
126 return function_overridden;
127}
128
129extern "C"
130 __declspec(dllexport) bool __cdecl __sanitizer_register_weak_function(
131 const char *export_name, const uptr user_function,
132 uptr *const old_user_function) {
133 CHECK(export_name);
134 CHECK(user_function);
135
136 const uptr sanitizer_function = GetSanitizerDllExport(export_name);
137
138 const bool function_overridden = __interception::OverrideFunction(
139 sanitizer_function, user_function, old_user_function);
140 if (!function_overridden) {
141 Report(
142 "ERROR: Failed to register local function at '%p' to be used in "
143 "place of sanitizer function '%s'\n.",
144 user_function, export_name);
145 CHECK("Failed to register weak function." && 0);
146 }
147
148 // Note that thread-safety of RunWeakFunctionCallbacks in InitializeFlags
149 // depends on __sanitizer_register_weak_functions being called during the
150 // loader lock.
151 RunWeakFunctionCallbacks(sanitizer_function);
152
153 return function_overridden;
154}
155
156#endif // SANITIZER_WINDOWS
lib/tsan/sanitizer_common/sanitizer_win_interception.h created+32
...@@ -0,0 +1,32 @@
1//===-- sanitizer_win_interception.h ---------------------- --*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Windows-specific export surface to provide interception for parts of the
10// runtime that are always statically linked, both for overriding user-defined
11// functions as well as registering weak functions that the ASAN runtime should
12// use over defaults.
13//
14//===----------------------------------------------------------------------===//
15
16#ifndef SANITIZER_WIN_INTERCEPTION_H
17#define SANITIZER_WIN_INTERCEPTION_H
18
19#include "sanitizer_platform.h"
20#if SANITIZER_WINDOWS
21
22# include "sanitizer_common.h"
23# include "sanitizer_internal_defs.h"
24
25namespace __sanitizer {
26using RegisterWeakFunctionCallback = void (*)();
27void AddRegisterWeakFunctionCallback(uptr export_address,
28 RegisterWeakFunctionCallback cb);
29} // namespace __sanitizer
30
31#endif // SANITIZER_WINDOWS
32#endif // SANITIZER_WIN_INTERCEPTION_H
\ No newline at end of file
lib/tsan/sanitizer_common/sanitizer_win_weak_interception.cpp deleted-94
...@@ -1,94 +0,0 @@
1//===-- sanitizer_win_weak_interception.cpp -------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8// This module should be included in the sanitizer when it is implemented as a
9// shared library on Windows (dll), in order to delegate the calls of weak
10// functions to the implementation in the main executable when a strong
11// definition is provided.
12//===----------------------------------------------------------------------===//
13
14#include "sanitizer_platform.h"
15#if SANITIZER_WINDOWS && SANITIZER_DYNAMIC
16#include "sanitizer_win_weak_interception.h"
17#include "sanitizer_allocator_interface.h"
18#include "sanitizer_interface_internal.h"
19#include "sanitizer_win_defs.h"
20#include "interception/interception.h"
21
22extern "C" {
23void *WINAPI GetModuleHandleA(const char *module_name);
24void abort();
25}
26
27namespace __sanitizer {
28// Try to get a pointer to real_function in the main module and override
29// dll_function with that pointer. If the function isn't found, nothing changes.
30int interceptWhenPossible(uptr dll_function, const char *real_function) {
31 uptr real = __interception::InternalGetProcAddress(
32 (void *)GetModuleHandleA(0), real_function);
33 if (real && !__interception::OverrideFunction((uptr)dll_function, real, 0))
34 abort();
35 return 0;
36}
37} // namespace __sanitizer
38
39// Declare weak hooks.
40extern "C" {
41void __sanitizer_on_print(const char *str);
42void __sanitizer_weak_hook_memcmp(uptr called_pc, const void *s1,
43 const void *s2, uptr n, int result);
44void __sanitizer_weak_hook_strcmp(uptr called_pc, const char *s1,
45 const char *s2, int result);
46void __sanitizer_weak_hook_strncmp(uptr called_pc, const char *s1,
47 const char *s2, uptr n, int result);
48void __sanitizer_weak_hook_strstr(uptr called_pc, const char *s1,
49 const char *s2, char *result);
50}
51
52// Include Sanitizer Common interface.
53#define INTERFACE_FUNCTION(Name)
54#define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name)
55#include "sanitizer_common_interface.inc"
56
57#pragma section(".WEAK$A", read)
58#pragma section(".WEAK$Z", read)
59
60typedef void (*InterceptCB)();
61extern "C" {
62__declspec(allocate(".WEAK$A")) InterceptCB __start_weak_list;
63__declspec(allocate(".WEAK$Z")) InterceptCB __stop_weak_list;
64}
65
66static int weak_intercept_init() {
67 static bool flag = false;
68 // weak_interception_init is expected to be called by only one thread.
69 if (flag) return 0;
70 flag = true;
71
72 for (InterceptCB *it = &__start_weak_list; it < &__stop_weak_list; ++it)
73 if (*it)
74 (*it)();
75
76 // In DLLs, the callbacks are expected to return 0,
77 // otherwise CRT initialization fails.
78 return 0;
79}
80
81#pragma section(".CRT$XIB", long, read)
82__declspec(allocate(".CRT$XIB")) int (*__weak_intercept_preinit)() =
83 weak_intercept_init;
84
85static void WINAPI weak_intercept_thread_init(void *mod, unsigned long reason,
86 void *reserved) {
87 if (reason == /*DLL_PROCESS_ATTACH=*/1) weak_intercept_init();
88}
89
90#pragma section(".CRT$XLAB", long, read)
91__declspec(allocate(".CRT$XLAB")) void(WINAPI *__weak_intercept_tls_init)(
92 void *, unsigned long, void *) = weak_intercept_thread_init;
93
94#endif // SANITIZER_WINDOWS && SANITIZER_DYNAMIC
lib/tsan/sanitizer_common/sanitizer_win_weak_interception.h deleted-32
...@@ -1,32 +0,0 @@
1//===-- sanitizer_win_weak_interception.h ---------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8// This header provide helper macros to delegate calls of weak functions to the
9// implementation in the main executable when a strong definition is present.
10//===----------------------------------------------------------------------===//
11#ifndef SANITIZER_WIN_WEAK_INTERCEPTION_H
12#define SANITIZER_WIN_WEAK_INTERCEPTION_H
13#include "sanitizer_internal_defs.h"
14
15namespace __sanitizer {
16int interceptWhenPossible(uptr dll_function, const char *real_function);
17}
18
19// ----------------- Function interception helper macros -------------------- //
20// Weak functions, could be redefined in the main executable, but that is not
21// necessary, so we shouldn't die if we can not find a reference.
22#define INTERCEPT_WEAK(Name) interceptWhenPossible((uptr) Name, #Name);
23
24#define INTERCEPT_SANITIZER_WEAK_FUNCTION(Name) \
25 static int intercept_##Name() { \
26 return __sanitizer::interceptWhenPossible((__sanitizer::uptr) Name, #Name);\
27 } \
28 __pragma(section(".WEAK$M", long, read)) \
29 __declspec(allocate(".WEAK$M")) int (*__weak_intercept_##Name)() = \
30 intercept_##Name;
31
32#endif // SANITIZER_WIN_WEAK_INTERCEPTION_H
lib/tsan/tsan_interceptors_mac.cpp+123-97
...@@ -14,22 +14,21 @@...@@ -14,22 +14,21 @@
14#include "sanitizer_common/sanitizer_platform.h"14#include "sanitizer_common/sanitizer_platform.h"
15#if SANITIZER_APPLE15#if SANITIZER_APPLE
1616
17#include "interception/interception.h"17# include <errno.h>
18#include "tsan_interceptors.h"18# include <libkern/OSAtomic.h>
19#include "tsan_interface.h"19# include <objc/objc-sync.h>
20#include "tsan_interface_ann.h"20# include <os/lock.h>
21#include "tsan_spinlock_defs_mac.h"21# include <sys/ucontext.h>
22#include "sanitizer_common/sanitizer_addrhashmap.h"22
2323# include "interception/interception.h"
24#include <errno.h>24# include "sanitizer_common/sanitizer_addrhashmap.h"
25#include <libkern/OSAtomic.h>25# include "tsan_interceptors.h"
26#include <objc/objc-sync.h>26# include "tsan_interface.h"
27#include <os/lock.h>27# include "tsan_interface_ann.h"
28#include <sys/ucontext.h>28
2929# if defined(__has_include) && __has_include(<xpc/xpc.h>)
30#if defined(__has_include) && __has_include(<xpc/xpc.h>)30# include <xpc/xpc.h>
31#include <xpc/xpc.h>31# endif // #if defined(__has_include) && __has_include(<xpc/xpc.h>)
32#endif // #if defined(__has_include) && __has_include(<xpc/xpc.h>)
3332
34typedef long long_t;33typedef long long_t;
3534
...@@ -49,51 +48,55 @@ static constexpr morder kMacOrderBarrier = mo_acq_rel;...@@ -49,51 +48,55 @@ static constexpr morder kMacOrderBarrier = mo_acq_rel;
49static constexpr morder kMacOrderNonBarrier = mo_acq_rel;48static constexpr morder kMacOrderNonBarrier = mo_acq_rel;
50static constexpr morder kMacFailureOrder = mo_relaxed;49static constexpr morder kMacFailureOrder = mo_relaxed;
5150
52#define OSATOMIC_INTERCEPTOR(return_t, t, tsan_t, f, tsan_atomic_f, mo) \51# define OSATOMIC_INTERCEPTOR(return_t, t, tsan_t, f, tsan_atomic_f, mo) \
53 TSAN_INTERCEPTOR(return_t, f, t x, volatile t *ptr) { \52 TSAN_INTERCEPTOR(return_t, f, t x, volatile t *ptr) { \
54 SCOPED_TSAN_INTERCEPTOR(f, x, ptr); \53 SCOPED_TSAN_INTERCEPTOR(f, x, ptr); \
55 return tsan_atomic_f((volatile tsan_t *)ptr, x, mo); \54 return tsan_atomic_f((volatile tsan_t *)ptr, x, mo); \
56 }55 }
57
58#define OSATOMIC_INTERCEPTOR_PLUS_X(return_t, t, tsan_t, f, tsan_atomic_f, mo) \
59 TSAN_INTERCEPTOR(return_t, f, t x, volatile t *ptr) { \
60 SCOPED_TSAN_INTERCEPTOR(f, x, ptr); \
61 return tsan_atomic_f((volatile tsan_t *)ptr, x, mo) + x; \
62 }
6356
64#define OSATOMIC_INTERCEPTOR_PLUS_1(return_t, t, tsan_t, f, tsan_atomic_f, mo) \57# define OSATOMIC_INTERCEPTOR_PLUS_X(return_t, t, tsan_t, f, tsan_atomic_f, \
65 TSAN_INTERCEPTOR(return_t, f, volatile t *ptr) { \58 mo) \
66 SCOPED_TSAN_INTERCEPTOR(f, ptr); \59 TSAN_INTERCEPTOR(return_t, f, t x, volatile t *ptr) { \
67 return tsan_atomic_f((volatile tsan_t *)ptr, 1, mo) + 1; \60 SCOPED_TSAN_INTERCEPTOR(f, x, ptr); \
68 }61 return tsan_atomic_f((volatile tsan_t *)ptr, x, mo) + x; \
62 }
6963
70#define OSATOMIC_INTERCEPTOR_MINUS_1(return_t, t, tsan_t, f, tsan_atomic_f, \64# define OSATOMIC_INTERCEPTOR_PLUS_1(return_t, t, tsan_t, f, tsan_atomic_f, \
71 mo) \65 mo) \
72 TSAN_INTERCEPTOR(return_t, f, volatile t *ptr) { \66 TSAN_INTERCEPTOR(return_t, f, volatile t *ptr) { \
73 SCOPED_TSAN_INTERCEPTOR(f, ptr); \67 SCOPED_TSAN_INTERCEPTOR(f, ptr); \
74 return tsan_atomic_f((volatile tsan_t *)ptr, 1, mo) - 1; \68 return tsan_atomic_f((volatile tsan_t *)ptr, 1, mo) + 1; \
75 }69 }
7670
77#define OSATOMIC_INTERCEPTORS_ARITHMETIC(f, tsan_atomic_f, m) \71# define OSATOMIC_INTERCEPTOR_MINUS_1(return_t, t, tsan_t, f, tsan_atomic_f, \
78 m(int32_t, int32_t, a32, f##32, __tsan_atomic32_##tsan_atomic_f, \72 mo) \
79 kMacOrderNonBarrier) \73 TSAN_INTERCEPTOR(return_t, f, volatile t *ptr) { \
80 m(int32_t, int32_t, a32, f##32##Barrier, __tsan_atomic32_##tsan_atomic_f, \74 SCOPED_TSAN_INTERCEPTOR(f, ptr); \
81 kMacOrderBarrier) \75 return tsan_atomic_f((volatile tsan_t *)ptr, 1, mo) - 1; \
82 m(int64_t, int64_t, a64, f##64, __tsan_atomic64_##tsan_atomic_f, \76 }
83 kMacOrderNonBarrier) \
84 m(int64_t, int64_t, a64, f##64##Barrier, __tsan_atomic64_##tsan_atomic_f, \
85 kMacOrderBarrier)
86
87#define OSATOMIC_INTERCEPTORS_BITWISE(f, tsan_atomic_f, m, m_orig) \
88 m(int32_t, uint32_t, a32, f##32, __tsan_atomic32_##tsan_atomic_f, \
89 kMacOrderNonBarrier) \
90 m(int32_t, uint32_t, a32, f##32##Barrier, __tsan_atomic32_##tsan_atomic_f, \
91 kMacOrderBarrier) \
92 m_orig(int32_t, uint32_t, a32, f##32##Orig, __tsan_atomic32_##tsan_atomic_f, \
93 kMacOrderNonBarrier) \
94 m_orig(int32_t, uint32_t, a32, f##32##OrigBarrier, \
95 __tsan_atomic32_##tsan_atomic_f, kMacOrderBarrier)
9677
78# define OSATOMIC_INTERCEPTORS_ARITHMETIC(f, tsan_atomic_f, m) \
79 m(int32_t, int32_t, a32, f##32, __tsan_atomic32_##tsan_atomic_f, \
80 kMacOrderNonBarrier) \
81 m(int32_t, int32_t, a32, f##32##Barrier, \
82 __tsan_atomic32_##tsan_atomic_f, kMacOrderBarrier) \
83 m(int64_t, int64_t, a64, f##64, __tsan_atomic64_##tsan_atomic_f, \
84 kMacOrderNonBarrier) \
85 m(int64_t, int64_t, a64, f##64##Barrier, \
86 __tsan_atomic64_##tsan_atomic_f, kMacOrderBarrier)
87
88# define OSATOMIC_INTERCEPTORS_BITWISE(f, tsan_atomic_f, m, m_orig) \
89 m(int32_t, uint32_t, a32, f##32, __tsan_atomic32_##tsan_atomic_f, \
90 kMacOrderNonBarrier) \
91 m(int32_t, uint32_t, a32, f##32##Barrier, \
92 __tsan_atomic32_##tsan_atomic_f, kMacOrderBarrier) \
93 m_orig(int32_t, uint32_t, a32, f##32##Orig, \
94 __tsan_atomic32_##tsan_atomic_f, kMacOrderNonBarrier) \
95 m_orig(int32_t, uint32_t, a32, f##32##OrigBarrier, \
96 __tsan_atomic32_##tsan_atomic_f, kMacOrderBarrier)
97
98# pragma clang diagnostic push // OSAtomic* deprecation
99# pragma clang diagnostic ignored "-Wdeprecated-declarations"
97OSATOMIC_INTERCEPTORS_ARITHMETIC(OSAtomicAdd, fetch_add,100OSATOMIC_INTERCEPTORS_ARITHMETIC(OSAtomicAdd, fetch_add,
98 OSATOMIC_INTERCEPTOR_PLUS_X)101 OSATOMIC_INTERCEPTOR_PLUS_X)
99OSATOMIC_INTERCEPTORS_ARITHMETIC(OSAtomicIncrement, fetch_add,102OSATOMIC_INTERCEPTORS_ARITHMETIC(OSAtomicIncrement, fetch_add,
...@@ -106,23 +109,26 @@ OSATOMIC_INTERCEPTORS_BITWISE(OSAtomicAnd, fetch_and,...@@ -106,23 +109,26 @@ OSATOMIC_INTERCEPTORS_BITWISE(OSAtomicAnd, fetch_and,
106 OSATOMIC_INTERCEPTOR_PLUS_X, OSATOMIC_INTERCEPTOR)109 OSATOMIC_INTERCEPTOR_PLUS_X, OSATOMIC_INTERCEPTOR)
107OSATOMIC_INTERCEPTORS_BITWISE(OSAtomicXor, fetch_xor,110OSATOMIC_INTERCEPTORS_BITWISE(OSAtomicXor, fetch_xor,
108 OSATOMIC_INTERCEPTOR_PLUS_X, OSATOMIC_INTERCEPTOR)111 OSATOMIC_INTERCEPTOR_PLUS_X, OSATOMIC_INTERCEPTOR)
112# pragma clang diagnostic pop // OSAtomic* deprecation
113
114# define OSATOMIC_INTERCEPTORS_CAS(f, tsan_atomic_f, tsan_t, t) \
115 TSAN_INTERCEPTOR(bool, f, t old_value, t new_value, t volatile *ptr) { \
116 SCOPED_TSAN_INTERCEPTOR(f, old_value, new_value, ptr); \
117 return tsan_atomic_f##_compare_exchange_strong( \
118 (volatile tsan_t *)ptr, (tsan_t *)&old_value, (tsan_t)new_value, \
119 kMacOrderNonBarrier, kMacFailureOrder); \
120 } \
121 \
122 TSAN_INTERCEPTOR(bool, f##Barrier, t old_value, t new_value, \
123 t volatile *ptr) { \
124 SCOPED_TSAN_INTERCEPTOR(f##Barrier, old_value, new_value, ptr); \
125 return tsan_atomic_f##_compare_exchange_strong( \
126 (volatile tsan_t *)ptr, (tsan_t *)&old_value, (tsan_t)new_value, \
127 kMacOrderBarrier, kMacFailureOrder); \
128 }
109129
110#define OSATOMIC_INTERCEPTORS_CAS(f, tsan_atomic_f, tsan_t, t) \130# pragma clang diagnostic push // OSAtomicCompareAndSwap* deprecation
111 TSAN_INTERCEPTOR(bool, f, t old_value, t new_value, t volatile *ptr) { \131# pragma clang diagnostic ignored "-Wdeprecated-declarations"
112 SCOPED_TSAN_INTERCEPTOR(f, old_value, new_value, ptr); \
113 return tsan_atomic_f##_compare_exchange_strong( \
114 (volatile tsan_t *)ptr, (tsan_t *)&old_value, (tsan_t)new_value, \
115 kMacOrderNonBarrier, kMacFailureOrder); \
116 } \
117 \
118 TSAN_INTERCEPTOR(bool, f##Barrier, t old_value, t new_value, \
119 t volatile *ptr) { \
120 SCOPED_TSAN_INTERCEPTOR(f##Barrier, old_value, new_value, ptr); \
121 return tsan_atomic_f##_compare_exchange_strong( \
122 (volatile tsan_t *)ptr, (tsan_t *)&old_value, (tsan_t)new_value, \
123 kMacOrderBarrier, kMacFailureOrder); \
124 }
125
126OSATOMIC_INTERCEPTORS_CAS(OSAtomicCompareAndSwapInt, __tsan_atomic32, a32, int)132OSATOMIC_INTERCEPTORS_CAS(OSAtomicCompareAndSwapInt, __tsan_atomic32, a32, int)
127OSATOMIC_INTERCEPTORS_CAS(OSAtomicCompareAndSwapLong, __tsan_atomic64, a64,133OSATOMIC_INTERCEPTORS_CAS(OSAtomicCompareAndSwapLong, __tsan_atomic64, a64,
128 long_t)134 long_t)
...@@ -132,24 +138,28 @@ OSATOMIC_INTERCEPTORS_CAS(OSAtomicCompareAndSwap32, __tsan_atomic32, a32,...@@ -132,24 +138,28 @@ OSATOMIC_INTERCEPTORS_CAS(OSAtomicCompareAndSwap32, __tsan_atomic32, a32,
132 int32_t)138 int32_t)
133OSATOMIC_INTERCEPTORS_CAS(OSAtomicCompareAndSwap64, __tsan_atomic64, a64,139OSATOMIC_INTERCEPTORS_CAS(OSAtomicCompareAndSwap64, __tsan_atomic64, a64,
134 int64_t)140 int64_t)
141# pragma clang diagnostic pop // OSAtomicCompareAndSwap* deprecation
142
143# define OSATOMIC_INTERCEPTOR_BITOP(f, op, clear, mo) \
144 TSAN_INTERCEPTOR(bool, f, uint32_t n, volatile void *ptr) { \
145 SCOPED_TSAN_INTERCEPTOR(f, n, ptr); \
146 volatile char *byte_ptr = ((volatile char *)ptr) + (n >> 3); \
147 char bit = 0x80u >> (n & 7); \
148 char mask = clear ? ~bit : bit; \
149 char orig_byte = op((volatile a8 *)byte_ptr, mask, mo); \
150 return orig_byte & bit; \
151 }
135152
136#define OSATOMIC_INTERCEPTOR_BITOP(f, op, clear, mo) \153# define OSATOMIC_INTERCEPTORS_BITOP(f, op, clear) \
137 TSAN_INTERCEPTOR(bool, f, uint32_t n, volatile void *ptr) { \154 OSATOMIC_INTERCEPTOR_BITOP(f, op, clear, kMacOrderNonBarrier) \
138 SCOPED_TSAN_INTERCEPTOR(f, n, ptr); \155 OSATOMIC_INTERCEPTOR_BITOP(f##Barrier, op, clear, kMacOrderBarrier)
139 volatile char *byte_ptr = ((volatile char *)ptr) + (n >> 3); \
140 char bit = 0x80u >> (n & 7); \
141 char mask = clear ? ~bit : bit; \
142 char orig_byte = op((volatile a8 *)byte_ptr, mask, mo); \
143 return orig_byte & bit; \
144 }
145
146#define OSATOMIC_INTERCEPTORS_BITOP(f, op, clear) \
147 OSATOMIC_INTERCEPTOR_BITOP(f, op, clear, kMacOrderNonBarrier) \
148 OSATOMIC_INTERCEPTOR_BITOP(f##Barrier, op, clear, kMacOrderBarrier)
149156
157# pragma clang diagnostic push // OSAtomicTestAnd* deprecation
158# pragma clang diagnostic ignored "-Wdeprecated-declarations"
150OSATOMIC_INTERCEPTORS_BITOP(OSAtomicTestAndSet, __tsan_atomic8_fetch_or, false)159OSATOMIC_INTERCEPTORS_BITOP(OSAtomicTestAndSet, __tsan_atomic8_fetch_or, false)
151OSATOMIC_INTERCEPTORS_BITOP(OSAtomicTestAndClear, __tsan_atomic8_fetch_and,160OSATOMIC_INTERCEPTORS_BITOP(OSAtomicTestAndClear, __tsan_atomic8_fetch_and,
152 true)161 true)
162# pragma clang diagnostic pop // OSAtomicTestAnd* deprecation
153163
154TSAN_INTERCEPTOR(void, OSAtomicEnqueue, OSQueueHead *list, void *item,164TSAN_INTERCEPTOR(void, OSAtomicEnqueue, OSQueueHead *list, void *item,
155 size_t offset) {165 size_t offset) {
...@@ -161,12 +171,13 @@ TSAN_INTERCEPTOR(void, OSAtomicEnqueue, OSQueueHead *list, void *item,...@@ -161,12 +171,13 @@ TSAN_INTERCEPTOR(void, OSAtomicEnqueue, OSQueueHead *list, void *item,
161TSAN_INTERCEPTOR(void *, OSAtomicDequeue, OSQueueHead *list, size_t offset) {171TSAN_INTERCEPTOR(void *, OSAtomicDequeue, OSQueueHead *list, size_t offset) {
162 SCOPED_TSAN_INTERCEPTOR(OSAtomicDequeue, list, offset);172 SCOPED_TSAN_INTERCEPTOR(OSAtomicDequeue, list, offset);
163 void *item = REAL(OSAtomicDequeue)(list, offset);173 void *item = REAL(OSAtomicDequeue)(list, offset);
164 if (item) __tsan_acquire(item);174 if (item)
175 __tsan_acquire(item);
165 return item;176 return item;
166}177}
167178
168// OSAtomicFifoEnqueue and OSAtomicFifoDequeue are only on OS X.179// OSAtomicFifoEnqueue and OSAtomicFifoDequeue are only on OS X.
169#if !SANITIZER_IOS180# if !SANITIZER_IOS
170181
171TSAN_INTERCEPTOR(void, OSAtomicFifoEnqueue, OSFifoQueueHead *list, void *item,182TSAN_INTERCEPTOR(void, OSAtomicFifoEnqueue, OSFifoQueueHead *list, void *item,
172 size_t offset) {183 size_t offset) {
...@@ -179,11 +190,22 @@ TSAN_INTERCEPTOR(void *, OSAtomicFifoDequeue, OSFifoQueueHead *list,...@@ -179,11 +190,22 @@ TSAN_INTERCEPTOR(void *, OSAtomicFifoDequeue, OSFifoQueueHead *list,
179 size_t offset) {190 size_t offset) {
180 SCOPED_TSAN_INTERCEPTOR(OSAtomicFifoDequeue, list, offset);191 SCOPED_TSAN_INTERCEPTOR(OSAtomicFifoDequeue, list, offset);
181 void *item = REAL(OSAtomicFifoDequeue)(list, offset);192 void *item = REAL(OSAtomicFifoDequeue)(list, offset);
182 if (item) __tsan_acquire(item);193 if (item)
194 __tsan_acquire(item);
183 return item;195 return item;
184}196}
185197
186#endif198# endif
199
200// If `OSSPINLOCK_USE_INLINED=1` is set, then SDK headers don't declare these
201// as functions, but macros that call non-deprecated APIs. Undefine these
202// macros so they don't interfere with the interceptor machinery.
203# undef OSSpinLockLock
204# undef OSSpinLockTry
205# undef OSSpinLockUnlock
206
207# pragma clang diagnostic push // OSSpinLock* deprecation
208# pragma clang diagnostic ignored "-Wdeprecated-declarations"
187209
188TSAN_INTERCEPTOR(void, OSSpinLockLock, volatile OSSpinLock *lock) {210TSAN_INTERCEPTOR(void, OSSpinLockLock, volatile OSSpinLock *lock) {
189 CHECK(!cur_thread()->is_dead);211 CHECK(!cur_thread()->is_dead);
...@@ -216,6 +238,7 @@ TSAN_INTERCEPTOR(void, OSSpinLockUnlock, volatile OSSpinLock *lock) {...@@ -216,6 +238,7 @@ TSAN_INTERCEPTOR(void, OSSpinLockUnlock, volatile OSSpinLock *lock) {
216 Release(thr, pc, (uptr)lock);238 Release(thr, pc, (uptr)lock);
217 REAL(OSSpinLockUnlock)(lock);239 REAL(OSSpinLockUnlock)(lock);
218}240}
241# pragma clang diagnostic pop // OSSpinLock* deprecation
219242
220TSAN_INTERCEPTOR(void, os_lock_lock, void *lock) {243TSAN_INTERCEPTOR(void, os_lock_lock, void *lock) {
221 CHECK(!cur_thread()->is_dead);244 CHECK(!cur_thread()->is_dead);
...@@ -288,7 +311,7 @@ TSAN_INTERCEPTOR(void, os_unfair_lock_unlock, os_unfair_lock_t lock) {...@@ -288,7 +311,7 @@ TSAN_INTERCEPTOR(void, os_unfair_lock_unlock, os_unfair_lock_t lock) {
288 REAL(os_unfair_lock_unlock)(lock);311 REAL(os_unfair_lock_unlock)(lock);
289}312}
290313
291#if defined(__has_include) && __has_include(<xpc/xpc.h>)314# if defined(__has_include) && __has_include(<xpc/xpc.h>)
292315
293TSAN_INTERCEPTOR(void, xpc_connection_set_event_handler,316TSAN_INTERCEPTOR(void, xpc_connection_set_event_handler,
294 xpc_connection_t connection, xpc_handler_t handler) {317 xpc_connection_t connection, xpc_handler_t handler) {
...@@ -342,7 +365,7 @@ TSAN_INTERCEPTOR(void, xpc_connection_cancel, xpc_connection_t connection) {...@@ -342,7 +365,7 @@ TSAN_INTERCEPTOR(void, xpc_connection_cancel, xpc_connection_t connection) {
342 REAL(xpc_connection_cancel)(connection);365 REAL(xpc_connection_cancel)(connection);
343}366}
344367
345#endif // #if defined(__has_include) && __has_include(<xpc/xpc.h>)368# endif // #if defined(__has_include) && __has_include(<xpc/xpc.h>)
346369
347// Determines whether the Obj-C object pointer is a tagged pointer. Tagged370// Determines whether the Obj-C object pointer is a tagged pointer. Tagged
348// pointers encode the object data directly in their pointer bits and do not371// pointers encode the object data directly in their pointer bits and do not
...@@ -365,7 +388,7 @@ static uptr GetOrCreateSyncAddress(uptr addr, ThreadState *thr, uptr pc) {...@@ -365,7 +388,7 @@ static uptr GetOrCreateSyncAddress(uptr addr, ThreadState *thr, uptr pc) {
365 Map::Handle h(&Addresses, addr);388 Map::Handle h(&Addresses, addr);
366 if (h.created()) {389 if (h.created()) {
367 ThreadIgnoreBegin(thr, pc);390 ThreadIgnoreBegin(thr, pc);
368 *h = (uptr) user_alloc(thr, pc, /*size=*/1);391 *h = (uptr)user_alloc(thr, pc, /*size=*/1);
369 ThreadIgnoreEnd(thr);392 ThreadIgnoreEnd(thr);
370 }393 }
371 return *h;394 return *h;
...@@ -383,7 +406,8 @@ static uptr SyncAddressForObjCObject(id obj, ThreadState *thr, uptr pc) {...@@ -383,7 +406,8 @@ static uptr SyncAddressForObjCObject(id obj, ThreadState *thr, uptr pc) {
383406
384TSAN_INTERCEPTOR(int, objc_sync_enter, id obj) {407TSAN_INTERCEPTOR(int, objc_sync_enter, id obj) {
385 SCOPED_TSAN_INTERCEPTOR(objc_sync_enter, obj);408 SCOPED_TSAN_INTERCEPTOR(objc_sync_enter, obj);
386 if (!obj) return REAL(objc_sync_enter)(obj);409 if (!obj)
410 return REAL(objc_sync_enter)(obj);
387 uptr addr = SyncAddressForObjCObject(obj, thr, pc);411 uptr addr = SyncAddressForObjCObject(obj, thr, pc);
388 MutexPreLock(thr, pc, addr, MutexFlagWriteReentrant);412 MutexPreLock(thr, pc, addr, MutexFlagWriteReentrant);
389 int result = REAL(objc_sync_enter)(obj);413 int result = REAL(objc_sync_enter)(obj);
...@@ -394,11 +418,13 @@ TSAN_INTERCEPTOR(int, objc_sync_enter, id obj) {...@@ -394,11 +418,13 @@ TSAN_INTERCEPTOR(int, objc_sync_enter, id obj) {
394418
395TSAN_INTERCEPTOR(int, objc_sync_exit, id obj) {419TSAN_INTERCEPTOR(int, objc_sync_exit, id obj) {
396 SCOPED_TSAN_INTERCEPTOR(objc_sync_exit, obj);420 SCOPED_TSAN_INTERCEPTOR(objc_sync_exit, obj);
397 if (!obj) return REAL(objc_sync_exit)(obj);421 if (!obj)
422 return REAL(objc_sync_exit)(obj);
398 uptr addr = SyncAddressForObjCObject(obj, thr, pc);423 uptr addr = SyncAddressForObjCObject(obj, thr, pc);
399 MutexUnlock(thr, pc, addr);424 MutexUnlock(thr, pc, addr);
400 int result = REAL(objc_sync_exit)(obj);425 int result = REAL(objc_sync_exit)(obj);
401 if (result != OBJC_SYNC_SUCCESS) MutexInvalidAccess(thr, pc, addr);426 if (result != OBJC_SYNC_SUCCESS)
427 MutexInvalidAccess(thr, pc, addr);
402 return result;428 return result;
403}429}
404430
...@@ -429,7 +455,7 @@ TSAN_INTERCEPTOR(int, swapcontext, ucontext_t *oucp, const ucontext_t *ucp) {...@@ -429,7 +455,7 @@ TSAN_INTERCEPTOR(int, swapcontext, ucontext_t *oucp, const ucontext_t *ucp) {
429455
430// On macOS, libc++ is always linked dynamically, so intercepting works the456// On macOS, libc++ is always linked dynamically, so intercepting works the
431// usual way.457// usual way.
432#define STDCXX_INTERCEPTOR TSAN_INTERCEPTOR458# define STDCXX_INTERCEPTOR TSAN_INTERCEPTOR
433459
434namespace {460namespace {
435struct fake_shared_weak_count {461struct fake_shared_weak_count {
lib/tsan/tsan_interceptors_posix.cpp+45-17
...@@ -12,14 +12,15 @@...@@ -12,14 +12,15 @@
12// sanitizer_common/sanitizer_common_interceptors.inc12// sanitizer_common/sanitizer_common_interceptors.inc
13//===----------------------------------------------------------------------===//13//===----------------------------------------------------------------------===//
1414
15#include "sanitizer_common/sanitizer_allocator_dlsym.h"
15#include "sanitizer_common/sanitizer_atomic.h"16#include "sanitizer_common/sanitizer_atomic.h"
16#include "sanitizer_common/sanitizer_errno.h"17#include "sanitizer_common/sanitizer_errno.h"
17#include "sanitizer_common/sanitizer_glibc_version.h"18#include "sanitizer_common/sanitizer_glibc_version.h"
19#include "sanitizer_common/sanitizer_internal_defs.h"
18#include "sanitizer_common/sanitizer_libc.h"20#include "sanitizer_common/sanitizer_libc.h"
19#include "sanitizer_common/sanitizer_linux.h"21#include "sanitizer_common/sanitizer_linux.h"
20#include "sanitizer_common/sanitizer_platform_limits_netbsd.h"22#include "sanitizer_common/sanitizer_platform_limits_netbsd.h"
21#include "sanitizer_common/sanitizer_platform_limits_posix.h"23#include "sanitizer_common/sanitizer_platform_limits_posix.h"
22#include "sanitizer_common/sanitizer_placement_new.h"
23#include "sanitizer_common/sanitizer_posix.h"24#include "sanitizer_common/sanitizer_posix.h"
24#include "sanitizer_common/sanitizer_stacktrace.h"25#include "sanitizer_common/sanitizer_stacktrace.h"
25#include "sanitizer_common/sanitizer_tls_get_addr.h"26#include "sanitizer_common/sanitizer_tls_get_addr.h"
...@@ -96,7 +97,7 @@ extern "C" int pthread_key_create(unsigned *key, void (*destructor)(void* v));...@@ -96,7 +97,7 @@ extern "C" int pthread_key_create(unsigned *key, void (*destructor)(void* v));
96extern "C" int pthread_setspecific(unsigned key, const void *v);97extern "C" int pthread_setspecific(unsigned key, const void *v);
97DECLARE_REAL(int, pthread_mutexattr_gettype, void *, void *)98DECLARE_REAL(int, pthread_mutexattr_gettype, void *, void *)
98DECLARE_REAL(int, fflush, __sanitizer_FILE *fp)99DECLARE_REAL(int, fflush, __sanitizer_FILE *fp)
99DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr size)100DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, usize size)
100DECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr)101DECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr)
101extern "C" int pthread_equal(void *t1, void *t2);102extern "C" int pthread_equal(void *t1, void *t2);
102extern "C" void *pthread_self();103extern "C" void *pthread_self();
...@@ -252,6 +253,13 @@ SANITIZER_WEAK_CXX_DEFAULT_IMPL void OnPotentiallyBlockingRegionBegin() {}...@@ -252,6 +253,13 @@ SANITIZER_WEAK_CXX_DEFAULT_IMPL void OnPotentiallyBlockingRegionBegin() {}
252SANITIZER_WEAK_CXX_DEFAULT_IMPL void OnPotentiallyBlockingRegionEnd() {}253SANITIZER_WEAK_CXX_DEFAULT_IMPL void OnPotentiallyBlockingRegionEnd() {}
253#endif254#endif
254255
256// FIXME: Use for `in_symbolizer()` as well. As-is we can't use
257// `DlSymAllocator`, because it uses the primary allocator only. Symbolizer
258// requires support of the secondary allocator for larger blocks.
259struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> {
260 static bool UseImpl() { return (ctx && !ctx->initialized); }
261};
262
255} // namespace __tsan263} // namespace __tsan
256264
257static ThreadSignalContext *SigCtx(ThreadState *thr) {265static ThreadSignalContext *SigCtx(ThreadState *thr) {
...@@ -661,6 +669,8 @@ TSAN_INTERCEPTOR(void, _longjmp, uptr *env, int val) {...@@ -661,6 +669,8 @@ TSAN_INTERCEPTOR(void, _longjmp, uptr *env, int val) {
661TSAN_INTERCEPTOR(void*, malloc, uptr size) {669TSAN_INTERCEPTOR(void*, malloc, uptr size) {
662 if (in_symbolizer())670 if (in_symbolizer())
663 return InternalAlloc(size);671 return InternalAlloc(size);
672 if (DlsymAlloc::Use())
673 return DlsymAlloc::Allocate(size);
664 void *p = 0;674 void *p = 0;
665 {675 {
666 SCOPED_INTERCEPTOR_RAW(malloc, size);676 SCOPED_INTERCEPTOR_RAW(malloc, size);
...@@ -678,12 +688,14 @@ TSAN_INTERCEPTOR(void*, __libc_memalign, uptr align, uptr sz) {...@@ -678,12 +688,14 @@ TSAN_INTERCEPTOR(void*, __libc_memalign, uptr align, uptr sz) {
678 return user_memalign(thr, pc, align, sz);688 return user_memalign(thr, pc, align, sz);
679}689}
680690
681TSAN_INTERCEPTOR(void*, calloc, uptr size, uptr n) {691TSAN_INTERCEPTOR(void *, calloc, uptr n, uptr size) {
682 if (in_symbolizer())692 if (in_symbolizer())
683 return InternalCalloc(size, n);693 return InternalCalloc(n, size);
694 if (DlsymAlloc::Use())
695 return DlsymAlloc::Callocate(n, size);
684 void *p = 0;696 void *p = 0;
685 {697 {
686 SCOPED_INTERCEPTOR_RAW(calloc, size, n);698 SCOPED_INTERCEPTOR_RAW(calloc, n, size);
687 p = user_calloc(thr, pc, size, n);699 p = user_calloc(thr, pc, size, n);
688 }700 }
689 invoke_malloc_hook(p, n * size);701 invoke_malloc_hook(p, n * size);
...@@ -693,6 +705,8 @@ TSAN_INTERCEPTOR(void*, calloc, uptr size, uptr n) {...@@ -693,6 +705,8 @@ TSAN_INTERCEPTOR(void*, calloc, uptr size, uptr n) {
693TSAN_INTERCEPTOR(void*, realloc, void *p, uptr size) {705TSAN_INTERCEPTOR(void*, realloc, void *p, uptr size) {
694 if (in_symbolizer())706 if (in_symbolizer())
695 return InternalRealloc(p, size);707 return InternalRealloc(p, size);
708 if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(p))
709 return DlsymAlloc::Realloc(p, size);
696 if (p)710 if (p)
697 invoke_free_hook(p);711 invoke_free_hook(p);
698 {712 {
...@@ -703,13 +717,13 @@ TSAN_INTERCEPTOR(void*, realloc, void *p, uptr size) {...@@ -703,13 +717,13 @@ TSAN_INTERCEPTOR(void*, realloc, void *p, uptr size) {
703 return p;717 return p;
704}718}
705719
706TSAN_INTERCEPTOR(void*, reallocarray, void *p, uptr size, uptr n) {720TSAN_INTERCEPTOR(void *, reallocarray, void *p, uptr n, uptr size) {
707 if (in_symbolizer())721 if (in_symbolizer())
708 return InternalReallocArray(p, size, n);722 return InternalReallocArray(p, n, size);
709 if (p)723 if (p)
710 invoke_free_hook(p);724 invoke_free_hook(p);
711 {725 {
712 SCOPED_INTERCEPTOR_RAW(reallocarray, p, size, n);726 SCOPED_INTERCEPTOR_RAW(reallocarray, p, n, size);
713 p = user_reallocarray(thr, pc, p, size, n);727 p = user_reallocarray(thr, pc, p, size, n);
714 }728 }
715 invoke_malloc_hook(p, size);729 invoke_malloc_hook(p, size);
...@@ -717,20 +731,24 @@ TSAN_INTERCEPTOR(void*, reallocarray, void *p, uptr size, uptr n) {...@@ -717,20 +731,24 @@ TSAN_INTERCEPTOR(void*, reallocarray, void *p, uptr size, uptr n) {
717}731}
718732
719TSAN_INTERCEPTOR(void, free, void *p) {733TSAN_INTERCEPTOR(void, free, void *p) {
720 if (p == 0)734 if (UNLIKELY(!p))
721 return;735 return;
722 if (in_symbolizer())736 if (in_symbolizer())
723 return InternalFree(p);737 return InternalFree(p);
738 if (DlsymAlloc::PointerIsMine(p))
739 return DlsymAlloc::Free(p);
724 invoke_free_hook(p);740 invoke_free_hook(p);
725 SCOPED_INTERCEPTOR_RAW(free, p);741 SCOPED_INTERCEPTOR_RAW(free, p);
726 user_free(thr, pc, p);742 user_free(thr, pc, p);
727}743}
728744
729TSAN_INTERCEPTOR(void, cfree, void *p) {745TSAN_INTERCEPTOR(void, cfree, void *p) {
730 if (p == 0)746 if (UNLIKELY(!p))
731 return;747 return;
732 if (in_symbolizer())748 if (in_symbolizer())
733 return InternalFree(p);749 return InternalFree(p);
750 if (DlsymAlloc::PointerIsMine(p))
751 return DlsymAlloc::Free(p);
734 invoke_free_hook(p);752 invoke_free_hook(p);
735 SCOPED_INTERCEPTOR_RAW(cfree, p);753 SCOPED_INTERCEPTOR_RAW(cfree, p);
736 user_free(thr, pc, p);754 user_free(thr, pc, p);
...@@ -750,7 +768,7 @@ TSAN_INTERCEPTOR(char *, strcpy, char *dst, const char *src) {...@@ -750,7 +768,7 @@ TSAN_INTERCEPTOR(char *, strcpy, char *dst, const char *src) {
750 return REAL(strcpy)(dst, src);768 return REAL(strcpy)(dst, src);
751}769}
752770
753TSAN_INTERCEPTOR(char*, strncpy, char *dst, char *src, uptr n) {771TSAN_INTERCEPTOR(char*, strncpy, char *dst, char *src, usize n) {
754 SCOPED_TSAN_INTERCEPTOR(strncpy, dst, src, n);772 SCOPED_TSAN_INTERCEPTOR(strncpy, dst, src, n);
755 uptr srclen = internal_strnlen(src, n);773 uptr srclen = internal_strnlen(src, n);
756 MemoryAccessRange(thr, pc, (uptr)dst, n, true);774 MemoryAccessRange(thr, pc, (uptr)dst, n, true);
...@@ -1097,7 +1115,7 @@ int internal_pthread_create(void *th, void *attr, void *(*callback)(void *),...@@ -1097,7 +1115,7 @@ int internal_pthread_create(void *th, void *attr, void *(*callback)(void *),
1097}1115}
1098int internal_pthread_join(void *th, void **ret) {1116int internal_pthread_join(void *th, void **ret) {
1099 ScopedIgnoreInterceptors ignore;1117 ScopedIgnoreInterceptors ignore;
1100 return REAL(pthread_join(th, ret));1118 return REAL(pthread_join)(th, ret);
1101}1119}
1102} // namespace __sanitizer1120} // namespace __sanitizer
11031121
...@@ -1662,13 +1680,23 @@ TSAN_INTERCEPTOR(int, fstat64, int fd, void *buf) {...@@ -1662,13 +1680,23 @@ TSAN_INTERCEPTOR(int, fstat64, int fd, void *buf) {
1662#endif1680#endif
16631681
1664TSAN_INTERCEPTOR(int, open, const char *name, int oflag, ...) {1682TSAN_INTERCEPTOR(int, open, const char *name, int oflag, ...) {
1665 va_list ap;1683 mode_t mode = 0;
1666 va_start(ap, oflag);1684 if (OpenReadsVaArgs(oflag)) {
1667 mode_t mode = va_arg(ap, int);1685 va_list ap;
1668 va_end(ap);1686 va_start(ap, oflag);
1687 mode = va_arg(ap, int);
1688 va_end(ap);
1689 }
1690
1669 SCOPED_TSAN_INTERCEPTOR(open, name, oflag, mode);1691 SCOPED_TSAN_INTERCEPTOR(open, name, oflag, mode);
1670 READ_STRING(thr, pc, name, 0);1692 READ_STRING(thr, pc, name, 0);
1671 int fd = REAL(open)(name, oflag, mode);1693
1694 int fd;
1695 if (OpenReadsVaArgs(oflag))
1696 fd = REAL(open)(name, oflag, mode);
1697 else
1698 fd = REAL(open)(name, oflag);
1699
1672 if (fd >= 0)1700 if (fd >= 0)
1673 FdFileCreate(thr, pc, fd);1701 FdFileCreate(thr, pc, fd);
1674 return fd;1702 return fd;
lib/tsan/tsan_interface.h+76-75
...@@ -16,8 +16,8 @@...@@ -16,8 +16,8 @@
16#define TSAN_INTERFACE_H16#define TSAN_INTERFACE_H
1717
18#include <sanitizer_common/sanitizer_internal_defs.h>18#include <sanitizer_common/sanitizer_internal_defs.h>
19using __sanitizer::uptr;
20using __sanitizer::tid_t;19using __sanitizer::tid_t;
20using __sanitizer::uptr;
2121
22// This header should NOT include any other headers.22// This header should NOT include any other headers.
23// All functions in this header are extern "C" and start with __tsan_.23// All functions in this header are extern "C" and start with __tsan_.
...@@ -203,17 +203,18 @@ int __tsan_get_alloc_stack(uptr addr, uptr *trace, uptr size, int *thread_id,...@@ -203,17 +203,18 @@ int __tsan_get_alloc_stack(uptr addr, uptr *trace, uptr size, int *thread_id,
203namespace __tsan {203namespace __tsan {
204204
205// These should match declarations from public tsan_interface_atomic.h header.205// These should match declarations from public tsan_interface_atomic.h header.
206typedef unsigned char a8;206typedef unsigned char a8;
207typedef unsigned short a16;207typedef unsigned short a16;
208typedef unsigned int a32;208typedef unsigned int a32;
209typedef unsigned long long a64;209typedef unsigned long long a64;
210#if !SANITIZER_GO && (defined(__SIZEOF_INT128__) \210#if !SANITIZER_GO && \
211 || (__clang_major__ * 100 + __clang_minor__ >= 302)) && \211 (defined(__SIZEOF_INT128__) || \
212 (__clang_major__ * 100 + __clang_minor__ >= 302)) && \
212 !defined(__mips64) && !defined(__s390x__)213 !defined(__mips64) && !defined(__s390x__)
213__extension__ typedef __int128 a128;214__extension__ typedef __int128 a128;
214# define __TSAN_HAS_INT128 1215# define __TSAN_HAS_INT128 1
215#else216#else
216# define __TSAN_HAS_INT128 0217# define __TSAN_HAS_INT128 0
217#endif218#endif
218219
219// Part of ABI, do not change.220// Part of ABI, do not change.
...@@ -231,180 +232,180 @@ struct ThreadState;...@@ -231,180 +232,180 @@ struct ThreadState;
231232
232extern "C" {233extern "C" {
233SANITIZER_INTERFACE_ATTRIBUTE234SANITIZER_INTERFACE_ATTRIBUTE
234a8 __tsan_atomic8_load(const volatile a8 *a, morder mo);235a8 __tsan_atomic8_load(const volatile a8 *a, int mo);
235SANITIZER_INTERFACE_ATTRIBUTE236SANITIZER_INTERFACE_ATTRIBUTE
236a16 __tsan_atomic16_load(const volatile a16 *a, morder mo);237a16 __tsan_atomic16_load(const volatile a16 *a, int mo);
237SANITIZER_INTERFACE_ATTRIBUTE238SANITIZER_INTERFACE_ATTRIBUTE
238a32 __tsan_atomic32_load(const volatile a32 *a, morder mo);239a32 __tsan_atomic32_load(const volatile a32 *a, int mo);
239SANITIZER_INTERFACE_ATTRIBUTE240SANITIZER_INTERFACE_ATTRIBUTE
240a64 __tsan_atomic64_load(const volatile a64 *a, morder mo);241a64 __tsan_atomic64_load(const volatile a64 *a, int mo);
241#if __TSAN_HAS_INT128242#if __TSAN_HAS_INT128
242SANITIZER_INTERFACE_ATTRIBUTE243SANITIZER_INTERFACE_ATTRIBUTE
243a128 __tsan_atomic128_load(const volatile a128 *a, morder mo);244a128 __tsan_atomic128_load(const volatile a128 *a, int mo);
244#endif245#endif
245246
246SANITIZER_INTERFACE_ATTRIBUTE247SANITIZER_INTERFACE_ATTRIBUTE
247void __tsan_atomic8_store(volatile a8 *a, a8 v, morder mo);248void __tsan_atomic8_store(volatile a8 *a, a8 v, int mo);
248SANITIZER_INTERFACE_ATTRIBUTE249SANITIZER_INTERFACE_ATTRIBUTE
249void __tsan_atomic16_store(volatile a16 *a, a16 v, morder mo);250void __tsan_atomic16_store(volatile a16 *a, a16 v, int mo);
250SANITIZER_INTERFACE_ATTRIBUTE251SANITIZER_INTERFACE_ATTRIBUTE
251void __tsan_atomic32_store(volatile a32 *a, a32 v, morder mo);252void __tsan_atomic32_store(volatile a32 *a, a32 v, int mo);
252SANITIZER_INTERFACE_ATTRIBUTE253SANITIZER_INTERFACE_ATTRIBUTE
253void __tsan_atomic64_store(volatile a64 *a, a64 v, morder mo);254void __tsan_atomic64_store(volatile a64 *a, a64 v, int mo);
254#if __TSAN_HAS_INT128255#if __TSAN_HAS_INT128
255SANITIZER_INTERFACE_ATTRIBUTE256SANITIZER_INTERFACE_ATTRIBUTE
256void __tsan_atomic128_store(volatile a128 *a, a128 v, morder mo);257void __tsan_atomic128_store(volatile a128 *a, a128 v, int mo);
257#endif258#endif
258259
259SANITIZER_INTERFACE_ATTRIBUTE260SANITIZER_INTERFACE_ATTRIBUTE
260a8 __tsan_atomic8_exchange(volatile a8 *a, a8 v, morder mo);261a8 __tsan_atomic8_exchange(volatile a8 *a, a8 v, int mo);
261SANITIZER_INTERFACE_ATTRIBUTE262SANITIZER_INTERFACE_ATTRIBUTE
262a16 __tsan_atomic16_exchange(volatile a16 *a, a16 v, morder mo);263a16 __tsan_atomic16_exchange(volatile a16 *a, a16 v, int mo);
263SANITIZER_INTERFACE_ATTRIBUTE264SANITIZER_INTERFACE_ATTRIBUTE
264a32 __tsan_atomic32_exchange(volatile a32 *a, a32 v, morder mo);265a32 __tsan_atomic32_exchange(volatile a32 *a, a32 v, int mo);
265SANITIZER_INTERFACE_ATTRIBUTE266SANITIZER_INTERFACE_ATTRIBUTE
266a64 __tsan_atomic64_exchange(volatile a64 *a, a64 v, morder mo);267a64 __tsan_atomic64_exchange(volatile a64 *a, a64 v, int mo);
267#if __TSAN_HAS_INT128268#if __TSAN_HAS_INT128
268SANITIZER_INTERFACE_ATTRIBUTE269SANITIZER_INTERFACE_ATTRIBUTE
269a128 __tsan_atomic128_exchange(volatile a128 *a, a128 v, morder mo);270a128 __tsan_atomic128_exchange(volatile a128 *a, a128 v, int mo);
270#endif271#endif
271272
272SANITIZER_INTERFACE_ATTRIBUTE273SANITIZER_INTERFACE_ATTRIBUTE
273a8 __tsan_atomic8_fetch_add(volatile a8 *a, a8 v, morder mo);274a8 __tsan_atomic8_fetch_add(volatile a8 *a, a8 v, int mo);
274SANITIZER_INTERFACE_ATTRIBUTE275SANITIZER_INTERFACE_ATTRIBUTE
275a16 __tsan_atomic16_fetch_add(volatile a16 *a, a16 v, morder mo);276a16 __tsan_atomic16_fetch_add(volatile a16 *a, a16 v, int mo);
276SANITIZER_INTERFACE_ATTRIBUTE277SANITIZER_INTERFACE_ATTRIBUTE
277a32 __tsan_atomic32_fetch_add(volatile a32 *a, a32 v, morder mo);278a32 __tsan_atomic32_fetch_add(volatile a32 *a, a32 v, int mo);
278SANITIZER_INTERFACE_ATTRIBUTE279SANITIZER_INTERFACE_ATTRIBUTE
279a64 __tsan_atomic64_fetch_add(volatile a64 *a, a64 v, morder mo);280a64 __tsan_atomic64_fetch_add(volatile a64 *a, a64 v, int mo);
280#if __TSAN_HAS_INT128281#if __TSAN_HAS_INT128
281SANITIZER_INTERFACE_ATTRIBUTE282SANITIZER_INTERFACE_ATTRIBUTE
282a128 __tsan_atomic128_fetch_add(volatile a128 *a, a128 v, morder mo);283a128 __tsan_atomic128_fetch_add(volatile a128 *a, a128 v, int mo);
283#endif284#endif
284285
285SANITIZER_INTERFACE_ATTRIBUTE286SANITIZER_INTERFACE_ATTRIBUTE
286a8 __tsan_atomic8_fetch_sub(volatile a8 *a, a8 v, morder mo);287a8 __tsan_atomic8_fetch_sub(volatile a8 *a, a8 v, int mo);
287SANITIZER_INTERFACE_ATTRIBUTE288SANITIZER_INTERFACE_ATTRIBUTE
288a16 __tsan_atomic16_fetch_sub(volatile a16 *a, a16 v, morder mo);289a16 __tsan_atomic16_fetch_sub(volatile a16 *a, a16 v, int mo);
289SANITIZER_INTERFACE_ATTRIBUTE290SANITIZER_INTERFACE_ATTRIBUTE
290a32 __tsan_atomic32_fetch_sub(volatile a32 *a, a32 v, morder mo);291a32 __tsan_atomic32_fetch_sub(volatile a32 *a, a32 v, int mo);
291SANITIZER_INTERFACE_ATTRIBUTE292SANITIZER_INTERFACE_ATTRIBUTE
292a64 __tsan_atomic64_fetch_sub(volatile a64 *a, a64 v, morder mo);293a64 __tsan_atomic64_fetch_sub(volatile a64 *a, a64 v, int mo);
293#if __TSAN_HAS_INT128294#if __TSAN_HAS_INT128
294SANITIZER_INTERFACE_ATTRIBUTE295SANITIZER_INTERFACE_ATTRIBUTE
295a128 __tsan_atomic128_fetch_sub(volatile a128 *a, a128 v, morder mo);296a128 __tsan_atomic128_fetch_sub(volatile a128 *a, a128 v, int mo);
296#endif297#endif
297298
298SANITIZER_INTERFACE_ATTRIBUTE299SANITIZER_INTERFACE_ATTRIBUTE
299a8 __tsan_atomic8_fetch_and(volatile a8 *a, a8 v, morder mo);300a8 __tsan_atomic8_fetch_and(volatile a8 *a, a8 v, int mo);
300SANITIZER_INTERFACE_ATTRIBUTE301SANITIZER_INTERFACE_ATTRIBUTE
301a16 __tsan_atomic16_fetch_and(volatile a16 *a, a16 v, morder mo);302a16 __tsan_atomic16_fetch_and(volatile a16 *a, a16 v, int mo);
302SANITIZER_INTERFACE_ATTRIBUTE303SANITIZER_INTERFACE_ATTRIBUTE
303a32 __tsan_atomic32_fetch_and(volatile a32 *a, a32 v, morder mo);304a32 __tsan_atomic32_fetch_and(volatile a32 *a, a32 v, int mo);
304SANITIZER_INTERFACE_ATTRIBUTE305SANITIZER_INTERFACE_ATTRIBUTE
305a64 __tsan_atomic64_fetch_and(volatile a64 *a, a64 v, morder mo);306a64 __tsan_atomic64_fetch_and(volatile a64 *a, a64 v, int mo);
306#if __TSAN_HAS_INT128307#if __TSAN_HAS_INT128
307SANITIZER_INTERFACE_ATTRIBUTE308SANITIZER_INTERFACE_ATTRIBUTE
308a128 __tsan_atomic128_fetch_and(volatile a128 *a, a128 v, morder mo);309a128 __tsan_atomic128_fetch_and(volatile a128 *a, a128 v, int mo);
309#endif310#endif
310311
311SANITIZER_INTERFACE_ATTRIBUTE312SANITIZER_INTERFACE_ATTRIBUTE
312a8 __tsan_atomic8_fetch_or(volatile a8 *a, a8 v, morder mo);313a8 __tsan_atomic8_fetch_or(volatile a8 *a, a8 v, int mo);
313SANITIZER_INTERFACE_ATTRIBUTE314SANITIZER_INTERFACE_ATTRIBUTE
314a16 __tsan_atomic16_fetch_or(volatile a16 *a, a16 v, morder mo);315a16 __tsan_atomic16_fetch_or(volatile a16 *a, a16 v, int mo);
315SANITIZER_INTERFACE_ATTRIBUTE316SANITIZER_INTERFACE_ATTRIBUTE
316a32 __tsan_atomic32_fetch_or(volatile a32 *a, a32 v, morder mo);317a32 __tsan_atomic32_fetch_or(volatile a32 *a, a32 v, int mo);
317SANITIZER_INTERFACE_ATTRIBUTE318SANITIZER_INTERFACE_ATTRIBUTE
318a64 __tsan_atomic64_fetch_or(volatile a64 *a, a64 v, morder mo);319a64 __tsan_atomic64_fetch_or(volatile a64 *a, a64 v, int mo);
319#if __TSAN_HAS_INT128320#if __TSAN_HAS_INT128
320SANITIZER_INTERFACE_ATTRIBUTE321SANITIZER_INTERFACE_ATTRIBUTE
321a128 __tsan_atomic128_fetch_or(volatile a128 *a, a128 v, morder mo);322a128 __tsan_atomic128_fetch_or(volatile a128 *a, a128 v, int mo);
322#endif323#endif
323324
324SANITIZER_INTERFACE_ATTRIBUTE325SANITIZER_INTERFACE_ATTRIBUTE
325a8 __tsan_atomic8_fetch_xor(volatile a8 *a, a8 v, morder mo);326a8 __tsan_atomic8_fetch_xor(volatile a8 *a, a8 v, int mo);
326SANITIZER_INTERFACE_ATTRIBUTE327SANITIZER_INTERFACE_ATTRIBUTE
327a16 __tsan_atomic16_fetch_xor(volatile a16 *a, a16 v, morder mo);328a16 __tsan_atomic16_fetch_xor(volatile a16 *a, a16 v, int mo);
328SANITIZER_INTERFACE_ATTRIBUTE329SANITIZER_INTERFACE_ATTRIBUTE
329a32 __tsan_atomic32_fetch_xor(volatile a32 *a, a32 v, morder mo);330a32 __tsan_atomic32_fetch_xor(volatile a32 *a, a32 v, int mo);
330SANITIZER_INTERFACE_ATTRIBUTE331SANITIZER_INTERFACE_ATTRIBUTE
331a64 __tsan_atomic64_fetch_xor(volatile a64 *a, a64 v, morder mo);332a64 __tsan_atomic64_fetch_xor(volatile a64 *a, a64 v, int mo);
332#if __TSAN_HAS_INT128333#if __TSAN_HAS_INT128
333SANITIZER_INTERFACE_ATTRIBUTE334SANITIZER_INTERFACE_ATTRIBUTE
334a128 __tsan_atomic128_fetch_xor(volatile a128 *a, a128 v, morder mo);335a128 __tsan_atomic128_fetch_xor(volatile a128 *a, a128 v, int mo);
335#endif336#endif
336337
337SANITIZER_INTERFACE_ATTRIBUTE338SANITIZER_INTERFACE_ATTRIBUTE
338a8 __tsan_atomic8_fetch_nand(volatile a8 *a, a8 v, morder mo);339a8 __tsan_atomic8_fetch_nand(volatile a8 *a, a8 v, int mo);
339SANITIZER_INTERFACE_ATTRIBUTE340SANITIZER_INTERFACE_ATTRIBUTE
340a16 __tsan_atomic16_fetch_nand(volatile a16 *a, a16 v, morder mo);341a16 __tsan_atomic16_fetch_nand(volatile a16 *a, a16 v, int mo);
341SANITIZER_INTERFACE_ATTRIBUTE342SANITIZER_INTERFACE_ATTRIBUTE
342a32 __tsan_atomic32_fetch_nand(volatile a32 *a, a32 v, morder mo);343a32 __tsan_atomic32_fetch_nand(volatile a32 *a, a32 v, int mo);
343SANITIZER_INTERFACE_ATTRIBUTE344SANITIZER_INTERFACE_ATTRIBUTE
344a64 __tsan_atomic64_fetch_nand(volatile a64 *a, a64 v, morder mo);345a64 __tsan_atomic64_fetch_nand(volatile a64 *a, a64 v, int mo);
345#if __TSAN_HAS_INT128346#if __TSAN_HAS_INT128
346SANITIZER_INTERFACE_ATTRIBUTE347SANITIZER_INTERFACE_ATTRIBUTE
347a128 __tsan_atomic128_fetch_nand(volatile a128 *a, a128 v, morder mo);348a128 __tsan_atomic128_fetch_nand(volatile a128 *a, a128 v, int mo);
348#endif349#endif
349350
350SANITIZER_INTERFACE_ATTRIBUTE351SANITIZER_INTERFACE_ATTRIBUTE
351int __tsan_atomic8_compare_exchange_strong(volatile a8 *a, a8 *c, a8 v,352int __tsan_atomic8_compare_exchange_strong(volatile a8 *a, a8 *c, a8 v, int mo,
352 morder mo, morder fmo);353 int fmo);
353SANITIZER_INTERFACE_ATTRIBUTE354SANITIZER_INTERFACE_ATTRIBUTE
354int __tsan_atomic16_compare_exchange_strong(volatile a16 *a, a16 *c, a16 v,355int __tsan_atomic16_compare_exchange_strong(volatile a16 *a, a16 *c, a16 v,
355 morder mo, morder fmo);356 int mo, int fmo);
356SANITIZER_INTERFACE_ATTRIBUTE357SANITIZER_INTERFACE_ATTRIBUTE
357int __tsan_atomic32_compare_exchange_strong(volatile a32 *a, a32 *c, a32 v,358int __tsan_atomic32_compare_exchange_strong(volatile a32 *a, a32 *c, a32 v,
358 morder mo, morder fmo);359 int mo, int fmo);
359SANITIZER_INTERFACE_ATTRIBUTE360SANITIZER_INTERFACE_ATTRIBUTE
360int __tsan_atomic64_compare_exchange_strong(volatile a64 *a, a64 *c, a64 v,361int __tsan_atomic64_compare_exchange_strong(volatile a64 *a, a64 *c, a64 v,
361 morder mo, morder fmo);362 int mo, int fmo);
362#if __TSAN_HAS_INT128363#if __TSAN_HAS_INT128
363SANITIZER_INTERFACE_ATTRIBUTE364SANITIZER_INTERFACE_ATTRIBUTE
364int __tsan_atomic128_compare_exchange_strong(volatile a128 *a, a128 *c, a128 v,365int __tsan_atomic128_compare_exchange_strong(volatile a128 *a, a128 *c, a128 v,
365 morder mo, morder fmo);366 int mo, int fmo);
366#endif367#endif
367368
368SANITIZER_INTERFACE_ATTRIBUTE369SANITIZER_INTERFACE_ATTRIBUTE
369int __tsan_atomic8_compare_exchange_weak(volatile a8 *a, a8 *c, a8 v, morder mo,370int __tsan_atomic8_compare_exchange_weak(volatile a8 *a, a8 *c, a8 v, int mo,
370 morder fmo);371 int fmo);
371SANITIZER_INTERFACE_ATTRIBUTE372SANITIZER_INTERFACE_ATTRIBUTE
372int __tsan_atomic16_compare_exchange_weak(volatile a16 *a, a16 *c, a16 v,373int __tsan_atomic16_compare_exchange_weak(volatile a16 *a, a16 *c, a16 v,
373 morder mo, morder fmo);374 int mo, int fmo);
374SANITIZER_INTERFACE_ATTRIBUTE375SANITIZER_INTERFACE_ATTRIBUTE
375int __tsan_atomic32_compare_exchange_weak(volatile a32 *a, a32 *c, a32 v,376int __tsan_atomic32_compare_exchange_weak(volatile a32 *a, a32 *c, a32 v,
376 morder mo, morder fmo);377 int mo, int fmo);
377SANITIZER_INTERFACE_ATTRIBUTE378SANITIZER_INTERFACE_ATTRIBUTE
378int __tsan_atomic64_compare_exchange_weak(volatile a64 *a, a64 *c, a64 v,379int __tsan_atomic64_compare_exchange_weak(volatile a64 *a, a64 *c, a64 v,
379 morder mo, morder fmo);380 int mo, int fmo);
380#if __TSAN_HAS_INT128381#if __TSAN_HAS_INT128
381SANITIZER_INTERFACE_ATTRIBUTE382SANITIZER_INTERFACE_ATTRIBUTE
382int __tsan_atomic128_compare_exchange_weak(volatile a128 *a, a128 *c, a128 v,383int __tsan_atomic128_compare_exchange_weak(volatile a128 *a, a128 *c, a128 v,
383 morder mo, morder fmo);384 int mo, int fmo);
384#endif385#endif
385386
386SANITIZER_INTERFACE_ATTRIBUTE387SANITIZER_INTERFACE_ATTRIBUTE
387a8 __tsan_atomic8_compare_exchange_val(volatile a8 *a, a8 c, a8 v, morder mo,388a8 __tsan_atomic8_compare_exchange_val(volatile a8 *a, a8 c, a8 v, int mo,
388 morder fmo);389 int fmo);
389SANITIZER_INTERFACE_ATTRIBUTE390SANITIZER_INTERFACE_ATTRIBUTE
390a16 __tsan_atomic16_compare_exchange_val(volatile a16 *a, a16 c, a16 v,391a16 __tsan_atomic16_compare_exchange_val(volatile a16 *a, a16 c, a16 v, int mo,
391 morder mo, morder fmo);392 int fmo);
392SANITIZER_INTERFACE_ATTRIBUTE393SANITIZER_INTERFACE_ATTRIBUTE
393a32 __tsan_atomic32_compare_exchange_val(volatile a32 *a, a32 c, a32 v,394a32 __tsan_atomic32_compare_exchange_val(volatile a32 *a, a32 c, a32 v, int mo,
394 morder mo, morder fmo);395 int fmo);
395SANITIZER_INTERFACE_ATTRIBUTE396SANITIZER_INTERFACE_ATTRIBUTE
396a64 __tsan_atomic64_compare_exchange_val(volatile a64 *a, a64 c, a64 v,397a64 __tsan_atomic64_compare_exchange_val(volatile a64 *a, a64 c, a64 v, int mo,
397 morder mo, morder fmo);398 int fmo);
398#if __TSAN_HAS_INT128399#if __TSAN_HAS_INT128
399SANITIZER_INTERFACE_ATTRIBUTE400SANITIZER_INTERFACE_ATTRIBUTE
400a128 __tsan_atomic128_compare_exchange_val(volatile a128 *a, a128 c, a128 v,401a128 __tsan_atomic128_compare_exchange_val(volatile a128 *a, a128 c, a128 v,
401 morder mo, morder fmo);402 int mo, int fmo);
402#endif403#endif
403404
404SANITIZER_INTERFACE_ATTRIBUTE405SANITIZER_INTERFACE_ATTRIBUTE
405void __tsan_atomic_thread_fence(morder mo);406void __tsan_atomic_thread_fence(int mo);
406SANITIZER_INTERFACE_ATTRIBUTE407SANITIZER_INTERFACE_ATTRIBUTE
407void __tsan_atomic_signal_fence(morder mo);408void __tsan_atomic_signal_fence(int mo);
408409
409SANITIZER_INTERFACE_ATTRIBUTE410SANITIZER_INTERFACE_ATTRIBUTE
410void __tsan_go_atomic32_load(ThreadState *thr, uptr cpc, uptr pc, u8 *a);411void __tsan_go_atomic32_load(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
lib/tsan/tsan_interface_atomic.cpp+476-430
...@@ -18,9 +18,9 @@...@@ -18,9 +18,9 @@
18// The following page contains more background information:18// The following page contains more background information:
19// http://www.hpl.hp.com/personal/Hans_Boehm/c++mm/19// http://www.hpl.hp.com/personal/Hans_Boehm/c++mm/
2020
21#include "sanitizer_common/sanitizer_mutex.h"
21#include "sanitizer_common/sanitizer_placement_new.h"22#include "sanitizer_common/sanitizer_placement_new.h"
22#include "sanitizer_common/sanitizer_stacktrace.h"23#include "sanitizer_common/sanitizer_stacktrace.h"
23#include "sanitizer_common/sanitizer_mutex.h"
24#include "tsan_flags.h"24#include "tsan_flags.h"
25#include "tsan_interface.h"25#include "tsan_interface.h"
26#include "tsan_rtl.h"26#include "tsan_rtl.h"
...@@ -34,8 +34,8 @@ static StaticSpinMutex mutex128;...@@ -34,8 +34,8 @@ static StaticSpinMutex mutex128;
3434
35#if SANITIZER_DEBUG35#if SANITIZER_DEBUG
36static bool IsLoadOrder(morder mo) {36static bool IsLoadOrder(morder mo) {
37 return mo == mo_relaxed || mo == mo_consume37 return mo == mo_relaxed || mo == mo_consume || mo == mo_acquire ||
38 || mo == mo_acquire || mo == mo_seq_cst;38 mo == mo_seq_cst;
39}39}
4040
41static bool IsStoreOrder(morder mo) {41static bool IsStoreOrder(morder mo) {
...@@ -48,42 +48,49 @@ static bool IsReleaseOrder(morder mo) {...@@ -48,42 +48,49 @@ static bool IsReleaseOrder(morder mo) {
48}48}
4949
50static bool IsAcquireOrder(morder mo) {50static bool IsAcquireOrder(morder mo) {
51 return mo == mo_consume || mo == mo_acquire51 return mo == mo_consume || mo == mo_acquire || mo == mo_acq_rel ||
52 || mo == mo_acq_rel || mo == mo_seq_cst;52 mo == mo_seq_cst;
53}53}
5454
55static bool IsAcqRelOrder(morder mo) {55static bool IsAcqRelOrder(morder mo) {
56 return mo == mo_acq_rel || mo == mo_seq_cst;56 return mo == mo_acq_rel || mo == mo_seq_cst;
57}57}
5858
59template<typename T> T func_xchg(volatile T *v, T op) {59template <typename T>
60T func_xchg(volatile T *v, T op) {
60 T res = __sync_lock_test_and_set(v, op);61 T res = __sync_lock_test_and_set(v, op);
61 // __sync_lock_test_and_set does not contain full barrier.62 // __sync_lock_test_and_set does not contain full barrier.
62 __sync_synchronize();63 __sync_synchronize();
63 return res;64 return res;
64}65}
6566
66template<typename T> T func_add(volatile T *v, T op) {67template <typename T>
68T func_add(volatile T *v, T op) {
67 return __sync_fetch_and_add(v, op);69 return __sync_fetch_and_add(v, op);
68}70}
6971
70template<typename T> T func_sub(volatile T *v, T op) {72template <typename T>
73T func_sub(volatile T *v, T op) {
71 return __sync_fetch_and_sub(v, op);74 return __sync_fetch_and_sub(v, op);
72}75}
7376
74template<typename T> T func_and(volatile T *v, T op) {77template <typename T>
78T func_and(volatile T *v, T op) {
75 return __sync_fetch_and_and(v, op);79 return __sync_fetch_and_and(v, op);
76}80}
7781
78template<typename T> T func_or(volatile T *v, T op) {82template <typename T>
83T func_or(volatile T *v, T op) {
79 return __sync_fetch_and_or(v, op);84 return __sync_fetch_and_or(v, op);
80}85}
8186
82template<typename T> T func_xor(volatile T *v, T op) {87template <typename T>
88T func_xor(volatile T *v, T op) {
83 return __sync_fetch_and_xor(v, op);89 return __sync_fetch_and_xor(v, op);
84}90}
8591
86template<typename T> T func_nand(volatile T *v, T op) {92template <typename T>
93T func_nand(volatile T *v, T op) {
87 // clang does not support __sync_fetch_and_nand.94 // clang does not support __sync_fetch_and_nand.
88 T cmp = *v;95 T cmp = *v;
89 for (;;) {96 for (;;) {
...@@ -95,7 +102,8 @@ template<typename T> T func_nand(volatile T *v, T op) {...@@ -95,7 +102,8 @@ template<typename T> T func_nand(volatile T *v, T op) {
95 }102 }
96}103}
97104
98template<typename T> T func_cas(volatile T *v, T cmp, T xch) {105template <typename T>
106T func_cas(volatile T *v, T cmp, T xch) {
99 return __sync_val_compare_and_swap(v, cmp, xch);107 return __sync_val_compare_and_swap(v, cmp, xch);
100}108}
101109
...@@ -103,8 +111,8 @@ template<typename T> T func_cas(volatile T *v, T cmp, T xch) {...@@ -103,8 +111,8 @@ template<typename T> T func_cas(volatile T *v, T cmp, T xch) {
103// Atomic ops are executed under tsan internal mutex,111// Atomic ops are executed under tsan internal mutex,
104// here we assume that the atomic variables are not accessed112// here we assume that the atomic variables are not accessed
105// from non-instrumented code.113// from non-instrumented code.
106#if !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) && !SANITIZER_GO \114#if !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) && !SANITIZER_GO && \
107 && __TSAN_HAS_INT128115 __TSAN_HAS_INT128
108a128 func_xchg(volatile a128 *v, a128 op) {116a128 func_xchg(volatile a128 *v, a128 op) {
109 SpinMutexLock lock(&mutex128);117 SpinMutexLock lock(&mutex128);
110 a128 cmp = *v;118 a128 cmp = *v;
...@@ -197,89 +205,24 @@ static atomic_uint64_t *to_atomic(const volatile a64 *a) {...@@ -197,89 +205,24 @@ static atomic_uint64_t *to_atomic(const volatile a64 *a) {
197205
198static memory_order to_mo(morder mo) {206static memory_order to_mo(morder mo) {
199 switch (mo) {207 switch (mo) {
200 case mo_relaxed: return memory_order_relaxed;208 case mo_relaxed:
201 case mo_consume: return memory_order_consume;209 return memory_order_relaxed;
202 case mo_acquire: return memory_order_acquire;210 case mo_consume:
203 case mo_release: return memory_order_release;211 return memory_order_consume;
204 case mo_acq_rel: return memory_order_acq_rel;212 case mo_acquire:
205 case mo_seq_cst: return memory_order_seq_cst;213 return memory_order_acquire;
214 case mo_release:
215 return memory_order_release;
216 case mo_acq_rel:
217 return memory_order_acq_rel;
218 case mo_seq_cst:
219 return memory_order_seq_cst;
206 }220 }
207 DCHECK(0);221 DCHECK(0);
208 return memory_order_seq_cst;222 return memory_order_seq_cst;
209}223}
210224
211template<typename T>225namespace {
212static T NoTsanAtomicLoad(const volatile T *a, morder mo) {
213 return atomic_load(to_atomic(a), to_mo(mo));
214}
215
216#if __TSAN_HAS_INT128 && !SANITIZER_GO
217static a128 NoTsanAtomicLoad(const volatile a128 *a, morder mo) {
218 SpinMutexLock lock(&mutex128);
219 return *a;
220}
221#endif
222
223template <typename T>
224static T AtomicLoad(ThreadState *thr, uptr pc, const volatile T *a, morder mo) {
225 DCHECK(IsLoadOrder(mo));
226 // This fast-path is critical for performance.
227 // Assume the access is atomic.
228 if (!IsAcquireOrder(mo)) {
229 MemoryAccess(thr, pc, (uptr)a, AccessSize<T>(),
230 kAccessRead | kAccessAtomic);
231 return NoTsanAtomicLoad(a, mo);
232 }
233 // Don't create sync object if it does not exist yet. For example, an atomic
234 // pointer is initialized to nullptr and then periodically acquire-loaded.
235 T v = NoTsanAtomicLoad(a, mo);
236 SyncVar *s = ctx->metamap.GetSyncIfExists((uptr)a);
237 if (s) {
238 SlotLocker locker(thr);
239 ReadLock lock(&s->mtx);
240 thr->clock.Acquire(s->clock);
241 // Re-read under sync mutex because we need a consistent snapshot
242 // of the value and the clock we acquire.
243 v = NoTsanAtomicLoad(a, mo);
244 }
245 MemoryAccess(thr, pc, (uptr)a, AccessSize<T>(), kAccessRead | kAccessAtomic);
246 return v;
247}
248
249template<typename T>
250static void NoTsanAtomicStore(volatile T *a, T v, morder mo) {
251 atomic_store(to_atomic(a), v, to_mo(mo));
252}
253
254#if __TSAN_HAS_INT128 && !SANITIZER_GO
255static void NoTsanAtomicStore(volatile a128 *a, a128 v, morder mo) {
256 SpinMutexLock lock(&mutex128);
257 *a = v;
258}
259#endif
260
261template <typename T>
262static void AtomicStore(ThreadState *thr, uptr pc, volatile T *a, T v,
263 morder mo) {
264 DCHECK(IsStoreOrder(mo));
265 MemoryAccess(thr, pc, (uptr)a, AccessSize<T>(), kAccessWrite | kAccessAtomic);
266 // This fast-path is critical for performance.
267 // Assume the access is atomic.
268 // Strictly saying even relaxed store cuts off release sequence,
269 // so must reset the clock.
270 if (!IsReleaseOrder(mo)) {
271 NoTsanAtomicStore(a, v, mo);
272 return;
273 }
274 SlotLocker locker(thr);
275 {
276 auto s = ctx->metamap.GetSyncOrCreate(thr, pc, (uptr)a, false);
277 Lock lock(&s->mtx);
278 thr->clock.ReleaseStore(&s->clock);
279 NoTsanAtomicStore(a, v, mo);
280 }
281 IncrementEpoch(thr);
282}
283226
284template <typename T, T (*F)(volatile T *v, T op)>227template <typename T, T (*F)(volatile T *v, T op)>
285static T AtomicRMW(ThreadState *thr, uptr pc, volatile T *a, T v, morder mo) {228static T AtomicRMW(ThreadState *thr, uptr pc, volatile T *a, T v, morder mo) {
...@@ -303,175 +246,265 @@ static T AtomicRMW(ThreadState *thr, uptr pc, volatile T *a, T v, morder mo) {...@@ -303,175 +246,265 @@ static T AtomicRMW(ThreadState *thr, uptr pc, volatile T *a, T v, morder mo) {
303 return v;246 return v;
304}247}
305248
306template<typename T>249struct OpLoad {
307static T NoTsanAtomicExchange(volatile T *a, T v, morder mo) {250 template <typename T>
308 return func_xchg(a, v);251 static T NoTsanAtomic(morder mo, const volatile T *a) {
309}252 return atomic_load(to_atomic(a), to_mo(mo));
253 }
310254
311template<typename T>255#if __TSAN_HAS_INT128 && !SANITIZER_GO
312static T NoTsanAtomicFetchAdd(volatile T *a, T v, morder mo) {256 static a128 NoTsanAtomic(morder mo, const volatile a128 *a) {
313 return func_add(a, v);257 SpinMutexLock lock(&mutex128);
314}258 return *a;
259 }
260#endif
315261
316template<typename T>262 template <typename T>
317static T NoTsanAtomicFetchSub(volatile T *a, T v, morder mo) {263 static T Atomic(ThreadState *thr, uptr pc, morder mo, const volatile T *a) {
318 return func_sub(a, v);264 DCHECK(IsLoadOrder(mo));
319}265 // This fast-path is critical for performance.
266 // Assume the access is atomic.
267 if (!IsAcquireOrder(mo)) {
268 MemoryAccess(thr, pc, (uptr)a, AccessSize<T>(),
269 kAccessRead | kAccessAtomic);
270 return NoTsanAtomic(mo, a);
271 }
272 // Don't create sync object if it does not exist yet. For example, an atomic
273 // pointer is initialized to nullptr and then periodically acquire-loaded.
274 T v = NoTsanAtomic(mo, a);
275 SyncVar *s = ctx->metamap.GetSyncIfExists((uptr)a);
276 if (s) {
277 SlotLocker locker(thr);
278 ReadLock lock(&s->mtx);
279 thr->clock.Acquire(s->clock);
280 // Re-read under sync mutex because we need a consistent snapshot
281 // of the value and the clock we acquire.
282 v = NoTsanAtomic(mo, a);
283 }
284 MemoryAccess(thr, pc, (uptr)a, AccessSize<T>(),
285 kAccessRead | kAccessAtomic);
286 return v;
287 }
288};
320289
321template<typename T>290struct OpStore {
322static T NoTsanAtomicFetchAnd(volatile T *a, T v, morder mo) {291 template <typename T>
323 return func_and(a, v);292 static void NoTsanAtomic(morder mo, volatile T *a, T v) {
324}293 atomic_store(to_atomic(a), v, to_mo(mo));
294 }
325295
326template<typename T>296#if __TSAN_HAS_INT128 && !SANITIZER_GO
327static T NoTsanAtomicFetchOr(volatile T *a, T v, morder mo) {297 static void NoTsanAtomic(morder mo, volatile a128 *a, a128 v) {
328 return func_or(a, v);298 SpinMutexLock lock(&mutex128);
329}299 *a = v;
300 }
301#endif
330302
331template<typename T>303 template <typename T>
332static T NoTsanAtomicFetchXor(volatile T *a, T v, morder mo) {304 static void Atomic(ThreadState *thr, uptr pc, morder mo, volatile T *a, T v) {
333 return func_xor(a, v);305 DCHECK(IsStoreOrder(mo));
334}306 MemoryAccess(thr, pc, (uptr)a, AccessSize<T>(),
307 kAccessWrite | kAccessAtomic);
308 // This fast-path is critical for performance.
309 // Assume the access is atomic.
310 // Strictly saying even relaxed store cuts off release sequence,
311 // so must reset the clock.
312 if (!IsReleaseOrder(mo)) {
313 NoTsanAtomic(mo, a, v);
314 return;
315 }
316 SlotLocker locker(thr);
317 {
318 auto s = ctx->metamap.GetSyncOrCreate(thr, pc, (uptr)a, false);
319 Lock lock(&s->mtx);
320 thr->clock.ReleaseStore(&s->clock);
321 NoTsanAtomic(mo, a, v);
322 }
323 IncrementEpoch(thr);
324 }
325};
335326
336template<typename T>327struct OpExchange {
337static T NoTsanAtomicFetchNand(volatile T *a, T v, morder mo) {328 template <typename T>
338 return func_nand(a, v);329 static T NoTsanAtomic(morder mo, volatile T *a, T v) {
339}330 return func_xchg(a, v);
331 }
332 template <typename T>
333 static T Atomic(ThreadState *thr, uptr pc, morder mo, volatile T *a, T v) {
334 return AtomicRMW<T, func_xchg>(thr, pc, a, v, mo);
335 }
336};
340337
341template<typename T>338struct OpFetchAdd {
342static T AtomicExchange(ThreadState *thr, uptr pc, volatile T *a, T v,339 template <typename T>
343 morder mo) {340 static T NoTsanAtomic(morder mo, volatile T *a, T v) {
344 return AtomicRMW<T, func_xchg>(thr, pc, a, v, mo);341 return func_add(a, v);
345}342 }
346343
347template<typename T>344 template <typename T>
348static T AtomicFetchAdd(ThreadState *thr, uptr pc, volatile T *a, T v,345 static T Atomic(ThreadState *thr, uptr pc, morder mo, volatile T *a, T v) {
349 morder mo) {346 return AtomicRMW<T, func_add>(thr, pc, a, v, mo);
350 return AtomicRMW<T, func_add>(thr, pc, a, v, mo);347 }
351}348};
352349
353template<typename T>350struct OpFetchSub {
354static T AtomicFetchSub(ThreadState *thr, uptr pc, volatile T *a, T v,351 template <typename T>
355 morder mo) {352 static T NoTsanAtomic(morder mo, volatile T *a, T v) {
356 return AtomicRMW<T, func_sub>(thr, pc, a, v, mo);353 return func_sub(a, v);
357}354 }
358355
359template<typename T>356 template <typename T>
360static T AtomicFetchAnd(ThreadState *thr, uptr pc, volatile T *a, T v,357 static T Atomic(ThreadState *thr, uptr pc, morder mo, volatile T *a, T v) {
361 morder mo) {358 return AtomicRMW<T, func_sub>(thr, pc, a, v, mo);
362 return AtomicRMW<T, func_and>(thr, pc, a, v, mo);359 }
363}360};
364361
365template<typename T>362struct OpFetchAnd {
366static T AtomicFetchOr(ThreadState *thr, uptr pc, volatile T *a, T v,363 template <typename T>
367 morder mo) {364 static T NoTsanAtomic(morder mo, volatile T *a, T v) {
368 return AtomicRMW<T, func_or>(thr, pc, a, v, mo);365 return func_and(a, v);
369}366 }
370367
371template<typename T>368 template <typename T>
372static T AtomicFetchXor(ThreadState *thr, uptr pc, volatile T *a, T v,369 static T Atomic(ThreadState *thr, uptr pc, morder mo, volatile T *a, T v) {
373 morder mo) {370 return AtomicRMW<T, func_and>(thr, pc, a, v, mo);
374 return AtomicRMW<T, func_xor>(thr, pc, a, v, mo);371 }
375}372};
376373
377template<typename T>374struct OpFetchOr {
378static T AtomicFetchNand(ThreadState *thr, uptr pc, volatile T *a, T v,375 template <typename T>
379 morder mo) {376 static T NoTsanAtomic(morder mo, volatile T *a, T v) {
380 return AtomicRMW<T, func_nand>(thr, pc, a, v, mo);377 return func_or(a, v);
381}378 }
382379
383template<typename T>380 template <typename T>
384static bool NoTsanAtomicCAS(volatile T *a, T *c, T v, morder mo, morder fmo) {381 static T Atomic(ThreadState *thr, uptr pc, morder mo, volatile T *a, T v) {
385 return atomic_compare_exchange_strong(to_atomic(a), c, v, to_mo(mo));382 return AtomicRMW<T, func_or>(thr, pc, a, v, mo);
386}383 }
384};
387385
388#if __TSAN_HAS_INT128386struct OpFetchXor {
389static bool NoTsanAtomicCAS(volatile a128 *a, a128 *c, a128 v,387 template <typename T>
390 morder mo, morder fmo) {388 static T NoTsanAtomic(morder mo, volatile T *a, T v) {
391 a128 old = *c;389 return func_xor(a, v);
392 a128 cur = func_cas(a, old, v);390 }
393 if (cur == old)
394 return true;
395 *c = cur;
396 return false;
397}
398#endif
399391
400template<typename T>392 template <typename T>
401static T NoTsanAtomicCAS(volatile T *a, T c, T v, morder mo, morder fmo) {393 static T Atomic(ThreadState *thr, uptr pc, morder mo, volatile T *a, T v) {
402 NoTsanAtomicCAS(a, &c, v, mo, fmo);394 return AtomicRMW<T, func_xor>(thr, pc, a, v, mo);
403 return c;395 }
404}396};
405397
406template <typename T>398struct OpFetchNand {
407static bool AtomicCAS(ThreadState *thr, uptr pc, volatile T *a, T *c, T v,399 template <typename T>
408 morder mo, morder fmo) {400 static T NoTsanAtomic(morder mo, volatile T *a, T v) {
409 // 31.7.2.18: "The failure argument shall not be memory_order_release401 return func_nand(a, v);
410 // nor memory_order_acq_rel". LLVM (2021-05) fallbacks to Monotonic402 }
411 // (mo_relaxed) when those are used.
412 DCHECK(IsLoadOrder(fmo));
413403
414 MemoryAccess(thr, pc, (uptr)a, AccessSize<T>(), kAccessWrite | kAccessAtomic);404 template <typename T>
415 if (LIKELY(mo == mo_relaxed && fmo == mo_relaxed)) {405 static T Atomic(ThreadState *thr, uptr pc, morder mo, volatile T *a, T v) {
416 T cc = *c;406 return AtomicRMW<T, func_nand>(thr, pc, a, v, mo);
417 T pr = func_cas(a, cc, v);407 }
418 if (pr == cc)408};
409
410struct OpCAS {
411 template <typename T>
412 static bool NoTsanAtomic(morder mo, morder fmo, volatile T *a, T *c, T v) {
413 return atomic_compare_exchange_strong(to_atomic(a), c, v, to_mo(mo));
414 }
415
416#if __TSAN_HAS_INT128
417 static bool NoTsanAtomic(morder mo, morder fmo, volatile a128 *a, a128 *c,
418 a128 v) {
419 a128 old = *c;
420 a128 cur = func_cas(a, old, v);
421 if (cur == old)
419 return true;422 return true;
420 *c = pr;423 *c = cur;
421 return false;424 return false;
422 }425 }
423 SlotLocker locker(thr);426#endif
424 bool release = IsReleaseOrder(mo);427
425 bool success;428 template <typename T>
426 {429 static T NoTsanAtomic(morder mo, morder fmo, volatile T *a, T c, T v) {
427 auto s = ctx->metamap.GetSyncOrCreate(thr, pc, (uptr)a, false);430 NoTsanAtomic(mo, fmo, a, &c, v);
428 RWLock lock(&s->mtx, release);431 return c;
429 T cc = *c;432 }
430 T pr = func_cas(a, cc, v);433
431 success = pr == cc;434 template <typename T>
432 if (!success) {435 static bool Atomic(ThreadState *thr, uptr pc, morder mo, morder fmo,
436 volatile T *a, T *c, T v) {
437 // 31.7.2.18: "The failure argument shall not be memory_order_release
438 // nor memory_order_acq_rel". LLVM (2021-05) fallbacks to Monotonic
439 // (mo_relaxed) when those are used.
440 DCHECK(IsLoadOrder(fmo));
441
442 MemoryAccess(thr, pc, (uptr)a, AccessSize<T>(),
443 kAccessWrite | kAccessAtomic);
444 if (LIKELY(mo == mo_relaxed && fmo == mo_relaxed)) {
445 T cc = *c;
446 T pr = func_cas(a, cc, v);
447 if (pr == cc)
448 return true;
433 *c = pr;449 *c = pr;
434 mo = fmo;450 return false;
435 }451 }
436 if (success && IsAcqRelOrder(mo))452 SlotLocker locker(thr);
437 thr->clock.ReleaseAcquire(&s->clock);453 bool release = IsReleaseOrder(mo);
438 else if (success && IsReleaseOrder(mo))454 bool success;
439 thr->clock.Release(&s->clock);455 {
440 else if (IsAcquireOrder(mo))456 auto s = ctx->metamap.GetSyncOrCreate(thr, pc, (uptr)a, false);
441 thr->clock.Acquire(s->clock);457 RWLock lock(&s->mtx, release);
458 T cc = *c;
459 T pr = func_cas(a, cc, v);
460 success = pr == cc;
461 if (!success) {
462 *c = pr;
463 mo = fmo;
464 }
465 if (success && IsAcqRelOrder(mo))
466 thr->clock.ReleaseAcquire(&s->clock);
467 else if (success && IsReleaseOrder(mo))
468 thr->clock.Release(&s->clock);
469 else if (IsAcquireOrder(mo))
470 thr->clock.Acquire(s->clock);
471 }
472 if (success && release)
473 IncrementEpoch(thr);
474 return success;
442 }475 }
443 if (success && release)
444 IncrementEpoch(thr);
445 return success;
446}
447476
448template<typename T>477 template <typename T>
449static T AtomicCAS(ThreadState *thr, uptr pc,478 static T Atomic(ThreadState *thr, uptr pc, morder mo, morder fmo,
450 volatile T *a, T c, T v, morder mo, morder fmo) {479 volatile T *a, T c, T v) {
451 AtomicCAS(thr, pc, a, &c, v, mo, fmo);480 Atomic(thr, pc, mo, fmo, a, &c, v);
452 return c;481 return c;
453}482 }
483};
454484
455#if !SANITIZER_GO485#if !SANITIZER_GO
456static void NoTsanAtomicFence(morder mo) {486struct OpFence {
457 __sync_synchronize();487 static void NoTsanAtomic(morder mo) { __sync_synchronize(); }
458}
459488
460static void AtomicFence(ThreadState *thr, uptr pc, morder mo) {489 static void Atomic(ThreadState *thr, uptr pc, morder mo) {
461 // FIXME(dvyukov): not implemented.490 // FIXME(dvyukov): not implemented.
462 __sync_synchronize();491 __sync_synchronize();
463}492 }
493};
464#endif494#endif
465495
496} // namespace
497
466// Interface functions follow.498// Interface functions follow.
467#if !SANITIZER_GO499#if !SANITIZER_GO
468500
469// C/C++501// C/C++
470502
471static morder convert_morder(morder mo) {503static morder convert_morder(morder mo) {
472 if (flags()->force_seq_cst_atomics)504 return flags()->force_seq_cst_atomics ? mo_seq_cst : mo;
473 return (morder)mo_seq_cst;505}
474506
507static morder to_morder(int mo) {
475 // Filter out additional memory order flags:508 // Filter out additional memory order flags:
476 // MEMMODEL_SYNC = 1 << 15509 // MEMMODEL_SYNC = 1 << 15
477 // __ATOMIC_HLE_ACQUIRE = 1 << 16510 // __ATOMIC_HLE_ACQUIRE = 1 << 16
...@@ -482,468 +515,481 @@ static morder convert_morder(morder mo) {...@@ -482,468 +515,481 @@ static morder convert_morder(morder mo) {
482 // since we use __sync_ atomics for actual atomic operations,515 // since we use __sync_ atomics for actual atomic operations,
483 // we can safely ignore it as well. It also subtly affects semantics,516 // we can safely ignore it as well. It also subtly affects semantics,
484 // but we don't model the difference.517 // but we don't model the difference.
485 return (morder)(mo & 0x7fff);518 morder res = static_cast<morder>(static_cast<u8>(mo));
519 DCHECK_LE(res, mo_seq_cst);
520 return res;
486}521}
487522
488# define ATOMIC_IMPL(func, ...) \523template <class Op, class... Types>
489 ThreadState *const thr = cur_thread(); \524ALWAYS_INLINE auto AtomicImpl(morder mo, Types... args) {
490 ProcessPendingSignals(thr); \525 ThreadState *const thr = cur_thread();
491 if (UNLIKELY(thr->ignore_sync || thr->ignore_interceptors)) \526 ProcessPendingSignals(thr);
492 return NoTsanAtomic##func(__VA_ARGS__); \527 if (UNLIKELY(thr->ignore_sync || thr->ignore_interceptors))
493 mo = convert_morder(mo); \528 return Op::NoTsanAtomic(mo, args...);
494 return Atomic##func(thr, GET_CALLER_PC(), __VA_ARGS__);529 return Op::Atomic(thr, GET_CALLER_PC(), convert_morder(mo), args...);
530}
495531
496extern "C" {532extern "C" {
497SANITIZER_INTERFACE_ATTRIBUTE533SANITIZER_INTERFACE_ATTRIBUTE
498a8 __tsan_atomic8_load(const volatile a8 *a, morder mo) {534a8 __tsan_atomic8_load(const volatile a8 *a, int mo) {
499 ATOMIC_IMPL(Load, a, mo);535 return AtomicImpl<OpLoad>(to_morder(mo), a);
500}536}
501537
502SANITIZER_INTERFACE_ATTRIBUTE538SANITIZER_INTERFACE_ATTRIBUTE
503a16 __tsan_atomic16_load(const volatile a16 *a, morder mo) {539a16 __tsan_atomic16_load(const volatile a16 *a, int mo) {
504 ATOMIC_IMPL(Load, a, mo);540 return AtomicImpl<OpLoad>(to_morder(mo), a);
505}541}
506542
507SANITIZER_INTERFACE_ATTRIBUTE543SANITIZER_INTERFACE_ATTRIBUTE
508a32 __tsan_atomic32_load(const volatile a32 *a, morder mo) {544a32 __tsan_atomic32_load(const volatile a32 *a, int mo) {
509 ATOMIC_IMPL(Load, a, mo);545 return AtomicImpl<OpLoad>(to_morder(mo), a);
510}546}
511547
512SANITIZER_INTERFACE_ATTRIBUTE548SANITIZER_INTERFACE_ATTRIBUTE
513a64 __tsan_atomic64_load(const volatile a64 *a, morder mo) {549a64 __tsan_atomic64_load(const volatile a64 *a, int mo) {
514 ATOMIC_IMPL(Load, a, mo);550 return AtomicImpl<OpLoad>(to_morder(mo), a);
515}551}
516552
517#if __TSAN_HAS_INT128553# if __TSAN_HAS_INT128
518SANITIZER_INTERFACE_ATTRIBUTE554SANITIZER_INTERFACE_ATTRIBUTE
519a128 __tsan_atomic128_load(const volatile a128 *a, morder mo) {555a128 __tsan_atomic128_load(const volatile a128 *a, int mo) {
520 ATOMIC_IMPL(Load, a, mo);556 return AtomicImpl<OpLoad>(to_morder(mo), a);
521}557}
522#endif558# endif
523559
524SANITIZER_INTERFACE_ATTRIBUTE560SANITIZER_INTERFACE_ATTRIBUTE
525void __tsan_atomic8_store(volatile a8 *a, a8 v, morder mo) {561void __tsan_atomic8_store(volatile a8 *a, a8 v, int mo) {
526 ATOMIC_IMPL(Store, a, v, mo);562 return AtomicImpl<OpStore>(to_morder(mo), a, v);
527}563}
528564
529SANITIZER_INTERFACE_ATTRIBUTE565SANITIZER_INTERFACE_ATTRIBUTE
530void __tsan_atomic16_store(volatile a16 *a, a16 v, morder mo) {566void __tsan_atomic16_store(volatile a16 *a, a16 v, int mo) {
531 ATOMIC_IMPL(Store, a, v, mo);567 return AtomicImpl<OpStore>(to_morder(mo), a, v);
532}568}
533569
534SANITIZER_INTERFACE_ATTRIBUTE570SANITIZER_INTERFACE_ATTRIBUTE
535void __tsan_atomic32_store(volatile a32 *a, a32 v, morder mo) {571void __tsan_atomic32_store(volatile a32 *a, a32 v, int mo) {
536 ATOMIC_IMPL(Store, a, v, mo);572 return AtomicImpl<OpStore>(to_morder(mo), a, v);
537}573}
538574
539SANITIZER_INTERFACE_ATTRIBUTE575SANITIZER_INTERFACE_ATTRIBUTE
540void __tsan_atomic64_store(volatile a64 *a, a64 v, morder mo) {576void __tsan_atomic64_store(volatile a64 *a, a64 v, int mo) {
541 ATOMIC_IMPL(Store, a, v, mo);577 return AtomicImpl<OpStore>(to_morder(mo), a, v);
542}578}
543579
544#if __TSAN_HAS_INT128580# if __TSAN_HAS_INT128
545SANITIZER_INTERFACE_ATTRIBUTE581SANITIZER_INTERFACE_ATTRIBUTE
546void __tsan_atomic128_store(volatile a128 *a, a128 v, morder mo) {582void __tsan_atomic128_store(volatile a128 *a, a128 v, int mo) {
547 ATOMIC_IMPL(Store, a, v, mo);583 return AtomicImpl<OpStore>(to_morder(mo), a, v);
548}584}
549#endif585# endif
550586
551SANITIZER_INTERFACE_ATTRIBUTE587SANITIZER_INTERFACE_ATTRIBUTE
552a8 __tsan_atomic8_exchange(volatile a8 *a, a8 v, morder mo) {588a8 __tsan_atomic8_exchange(volatile a8 *a, a8 v, int mo) {
553 ATOMIC_IMPL(Exchange, a, v, mo);589 return AtomicImpl<OpExchange>(to_morder(mo), a, v);
554}590}
555591
556SANITIZER_INTERFACE_ATTRIBUTE592SANITIZER_INTERFACE_ATTRIBUTE
557a16 __tsan_atomic16_exchange(volatile a16 *a, a16 v, morder mo) {593a16 __tsan_atomic16_exchange(volatile a16 *a, a16 v, int mo) {
558 ATOMIC_IMPL(Exchange, a, v, mo);594 return AtomicImpl<OpExchange>(to_morder(mo), a, v);
559}595}
560596
561SANITIZER_INTERFACE_ATTRIBUTE597SANITIZER_INTERFACE_ATTRIBUTE
562a32 __tsan_atomic32_exchange(volatile a32 *a, a32 v, morder mo) {598a32 __tsan_atomic32_exchange(volatile a32 *a, a32 v, int mo) {
563 ATOMIC_IMPL(Exchange, a, v, mo);599 return AtomicImpl<OpExchange>(to_morder(mo), a, v);
564}600}
565601
566SANITIZER_INTERFACE_ATTRIBUTE602SANITIZER_INTERFACE_ATTRIBUTE
567a64 __tsan_atomic64_exchange(volatile a64 *a, a64 v, morder mo) {603a64 __tsan_atomic64_exchange(volatile a64 *a, a64 v, int mo) {
568 ATOMIC_IMPL(Exchange, a, v, mo);604 return AtomicImpl<OpExchange>(to_morder(mo), a, v);
569}605}
570606
571#if __TSAN_HAS_INT128607# if __TSAN_HAS_INT128
572SANITIZER_INTERFACE_ATTRIBUTE608SANITIZER_INTERFACE_ATTRIBUTE
573a128 __tsan_atomic128_exchange(volatile a128 *a, a128 v, morder mo) {609a128 __tsan_atomic128_exchange(volatile a128 *a, a128 v, int mo) {
574 ATOMIC_IMPL(Exchange, a, v, mo);610 return AtomicImpl<OpExchange>(to_morder(mo), a, v);
575}611}
576#endif612# endif
577613
578SANITIZER_INTERFACE_ATTRIBUTE614SANITIZER_INTERFACE_ATTRIBUTE
579a8 __tsan_atomic8_fetch_add(volatile a8 *a, a8 v, morder mo) {615a8 __tsan_atomic8_fetch_add(volatile a8 *a, a8 v, int mo) {
580 ATOMIC_IMPL(FetchAdd, a, v, mo);616 return AtomicImpl<OpFetchAdd>(to_morder(mo), a, v);
581}617}
582618
583SANITIZER_INTERFACE_ATTRIBUTE619SANITIZER_INTERFACE_ATTRIBUTE
584a16 __tsan_atomic16_fetch_add(volatile a16 *a, a16 v, morder mo) {620a16 __tsan_atomic16_fetch_add(volatile a16 *a, a16 v, int mo) {
585 ATOMIC_IMPL(FetchAdd, a, v, mo);621 return AtomicImpl<OpFetchAdd>(to_morder(mo), a, v);
586}622}
587623
588SANITIZER_INTERFACE_ATTRIBUTE624SANITIZER_INTERFACE_ATTRIBUTE
589a32 __tsan_atomic32_fetch_add(volatile a32 *a, a32 v, morder mo) {625a32 __tsan_atomic32_fetch_add(volatile a32 *a, a32 v, int mo) {
590 ATOMIC_IMPL(FetchAdd, a, v, mo);626 return AtomicImpl<OpFetchAdd>(to_morder(mo), a, v);
591}627}
592628
593SANITIZER_INTERFACE_ATTRIBUTE629SANITIZER_INTERFACE_ATTRIBUTE
594a64 __tsan_atomic64_fetch_add(volatile a64 *a, a64 v, morder mo) {630a64 __tsan_atomic64_fetch_add(volatile a64 *a, a64 v, int mo) {
595 ATOMIC_IMPL(FetchAdd, a, v, mo);631 return AtomicImpl<OpFetchAdd>(to_morder(mo), a, v);
596}632}
597633
598#if __TSAN_HAS_INT128634# if __TSAN_HAS_INT128
599SANITIZER_INTERFACE_ATTRIBUTE635SANITIZER_INTERFACE_ATTRIBUTE
600a128 __tsan_atomic128_fetch_add(volatile a128 *a, a128 v, morder mo) {636a128 __tsan_atomic128_fetch_add(volatile a128 *a, a128 v, int mo) {
601 ATOMIC_IMPL(FetchAdd, a, v, mo);637 return AtomicImpl<OpFetchAdd>(to_morder(mo), a, v);
602}638}
603#endif639# endif
604640
605SANITIZER_INTERFACE_ATTRIBUTE641SANITIZER_INTERFACE_ATTRIBUTE
606a8 __tsan_atomic8_fetch_sub(volatile a8 *a, a8 v, morder mo) {642a8 __tsan_atomic8_fetch_sub(volatile a8 *a, a8 v, int mo) {
607 ATOMIC_IMPL(FetchSub, a, v, mo);643 return AtomicImpl<OpFetchSub>(to_morder(mo), a, v);
608}644}
609645
610SANITIZER_INTERFACE_ATTRIBUTE646SANITIZER_INTERFACE_ATTRIBUTE
611a16 __tsan_atomic16_fetch_sub(volatile a16 *a, a16 v, morder mo) {647a16 __tsan_atomic16_fetch_sub(volatile a16 *a, a16 v, int mo) {
612 ATOMIC_IMPL(FetchSub, a, v, mo);648 return AtomicImpl<OpFetchSub>(to_morder(mo), a, v);
613}649}
614650
615SANITIZER_INTERFACE_ATTRIBUTE651SANITIZER_INTERFACE_ATTRIBUTE
616a32 __tsan_atomic32_fetch_sub(volatile a32 *a, a32 v, morder mo) {652a32 __tsan_atomic32_fetch_sub(volatile a32 *a, a32 v, int mo) {
617 ATOMIC_IMPL(FetchSub, a, v, mo);653 return AtomicImpl<OpFetchSub>(to_morder(mo), a, v);
618}654}
619655
620SANITIZER_INTERFACE_ATTRIBUTE656SANITIZER_INTERFACE_ATTRIBUTE
621a64 __tsan_atomic64_fetch_sub(volatile a64 *a, a64 v, morder mo) {657a64 __tsan_atomic64_fetch_sub(volatile a64 *a, a64 v, int mo) {
622 ATOMIC_IMPL(FetchSub, a, v, mo);658 return AtomicImpl<OpFetchSub>(to_morder(mo), a, v);
623}659}
624660
625#if __TSAN_HAS_INT128661# if __TSAN_HAS_INT128
626SANITIZER_INTERFACE_ATTRIBUTE662SANITIZER_INTERFACE_ATTRIBUTE
627a128 __tsan_atomic128_fetch_sub(volatile a128 *a, a128 v, morder mo) {663a128 __tsan_atomic128_fetch_sub(volatile a128 *a, a128 v, int mo) {
628 ATOMIC_IMPL(FetchSub, a, v, mo);664 return AtomicImpl<OpFetchSub>(to_morder(mo), a, v);
629}665}
630#endif666# endif
631667
632SANITIZER_INTERFACE_ATTRIBUTE668SANITIZER_INTERFACE_ATTRIBUTE
633a8 __tsan_atomic8_fetch_and(volatile a8 *a, a8 v, morder mo) {669a8 __tsan_atomic8_fetch_and(volatile a8 *a, a8 v, int mo) {
634 ATOMIC_IMPL(FetchAnd, a, v, mo);670 return AtomicImpl<OpFetchAnd>(to_morder(mo), a, v);
635}671}
636672
637SANITIZER_INTERFACE_ATTRIBUTE673SANITIZER_INTERFACE_ATTRIBUTE
638a16 __tsan_atomic16_fetch_and(volatile a16 *a, a16 v, morder mo) {674a16 __tsan_atomic16_fetch_and(volatile a16 *a, a16 v, int mo) {
639 ATOMIC_IMPL(FetchAnd, a, v, mo);675 return AtomicImpl<OpFetchAnd>(to_morder(mo), a, v);
640}676}
641677
642SANITIZER_INTERFACE_ATTRIBUTE678SANITIZER_INTERFACE_ATTRIBUTE
643a32 __tsan_atomic32_fetch_and(volatile a32 *a, a32 v, morder mo) {679a32 __tsan_atomic32_fetch_and(volatile a32 *a, a32 v, int mo) {
644 ATOMIC_IMPL(FetchAnd, a, v, mo);680 return AtomicImpl<OpFetchAnd>(to_morder(mo), a, v);
645}681}
646682
647SANITIZER_INTERFACE_ATTRIBUTE683SANITIZER_INTERFACE_ATTRIBUTE
648a64 __tsan_atomic64_fetch_and(volatile a64 *a, a64 v, morder mo) {684a64 __tsan_atomic64_fetch_and(volatile a64 *a, a64 v, int mo) {
649 ATOMIC_IMPL(FetchAnd, a, v, mo);685 return AtomicImpl<OpFetchAnd>(to_morder(mo), a, v);
650}686}
651687
652#if __TSAN_HAS_INT128688# if __TSAN_HAS_INT128
653SANITIZER_INTERFACE_ATTRIBUTE689SANITIZER_INTERFACE_ATTRIBUTE
654a128 __tsan_atomic128_fetch_and(volatile a128 *a, a128 v, morder mo) {690a128 __tsan_atomic128_fetch_and(volatile a128 *a, a128 v, int mo) {
655 ATOMIC_IMPL(FetchAnd, a, v, mo);691 return AtomicImpl<OpFetchAnd>(to_morder(mo), a, v);
656}692}
657#endif693# endif
658694
659SANITIZER_INTERFACE_ATTRIBUTE695SANITIZER_INTERFACE_ATTRIBUTE
660a8 __tsan_atomic8_fetch_or(volatile a8 *a, a8 v, morder mo) {696a8 __tsan_atomic8_fetch_or(volatile a8 *a, a8 v, int mo) {
661 ATOMIC_IMPL(FetchOr, a, v, mo);697 return AtomicImpl<OpFetchOr>(to_morder(mo), a, v);
662}698}
663699
664SANITIZER_INTERFACE_ATTRIBUTE700SANITIZER_INTERFACE_ATTRIBUTE
665a16 __tsan_atomic16_fetch_or(volatile a16 *a, a16 v, morder mo) {701a16 __tsan_atomic16_fetch_or(volatile a16 *a, a16 v, int mo) {
666 ATOMIC_IMPL(FetchOr, a, v, mo);702 return AtomicImpl<OpFetchOr>(to_morder(mo), a, v);
667}703}
668704
669SANITIZER_INTERFACE_ATTRIBUTE705SANITIZER_INTERFACE_ATTRIBUTE
670a32 __tsan_atomic32_fetch_or(volatile a32 *a, a32 v, morder mo) {706a32 __tsan_atomic32_fetch_or(volatile a32 *a, a32 v, int mo) {
671 ATOMIC_IMPL(FetchOr, a, v, mo);707 return AtomicImpl<OpFetchOr>(to_morder(mo), a, v);
672}708}
673709
674SANITIZER_INTERFACE_ATTRIBUTE710SANITIZER_INTERFACE_ATTRIBUTE
675a64 __tsan_atomic64_fetch_or(volatile a64 *a, a64 v, morder mo) {711a64 __tsan_atomic64_fetch_or(volatile a64 *a, a64 v, int mo) {
676 ATOMIC_IMPL(FetchOr, a, v, mo);712 return AtomicImpl<OpFetchOr>(to_morder(mo), a, v);
677}713}
678714
679#if __TSAN_HAS_INT128715# if __TSAN_HAS_INT128
680SANITIZER_INTERFACE_ATTRIBUTE716SANITIZER_INTERFACE_ATTRIBUTE
681a128 __tsan_atomic128_fetch_or(volatile a128 *a, a128 v, morder mo) {717a128 __tsan_atomic128_fetch_or(volatile a128 *a, a128 v, int mo) {
682 ATOMIC_IMPL(FetchOr, a, v, mo);718 return AtomicImpl<OpFetchOr>(to_morder(mo), a, v);
683}719}
684#endif720# endif
685721
686SANITIZER_INTERFACE_ATTRIBUTE722SANITIZER_INTERFACE_ATTRIBUTE
687a8 __tsan_atomic8_fetch_xor(volatile a8 *a, a8 v, morder mo) {723a8 __tsan_atomic8_fetch_xor(volatile a8 *a, a8 v, int mo) {
688 ATOMIC_IMPL(FetchXor, a, v, mo);724 return AtomicImpl<OpFetchXor>(to_morder(mo), a, v);
689}725}
690726
691SANITIZER_INTERFACE_ATTRIBUTE727SANITIZER_INTERFACE_ATTRIBUTE
692a16 __tsan_atomic16_fetch_xor(volatile a16 *a, a16 v, morder mo) {728a16 __tsan_atomic16_fetch_xor(volatile a16 *a, a16 v, int mo) {
693 ATOMIC_IMPL(FetchXor, a, v, mo);729 return AtomicImpl<OpFetchXor>(to_morder(mo), a, v);
694}730}
695731
696SANITIZER_INTERFACE_ATTRIBUTE732SANITIZER_INTERFACE_ATTRIBUTE
697a32 __tsan_atomic32_fetch_xor(volatile a32 *a, a32 v, morder mo) {733a32 __tsan_atomic32_fetch_xor(volatile a32 *a, a32 v, int mo) {
698 ATOMIC_IMPL(FetchXor, a, v, mo);734 return AtomicImpl<OpFetchXor>(to_morder(mo), a, v);
699}735}
700736
701SANITIZER_INTERFACE_ATTRIBUTE737SANITIZER_INTERFACE_ATTRIBUTE
702a64 __tsan_atomic64_fetch_xor(volatile a64 *a, a64 v, morder mo) {738a64 __tsan_atomic64_fetch_xor(volatile a64 *a, a64 v, int mo) {
703 ATOMIC_IMPL(FetchXor, a, v, mo);739 return AtomicImpl<OpFetchXor>(to_morder(mo), a, v);
704}740}
705741
706#if __TSAN_HAS_INT128742# if __TSAN_HAS_INT128
707SANITIZER_INTERFACE_ATTRIBUTE743SANITIZER_INTERFACE_ATTRIBUTE
708a128 __tsan_atomic128_fetch_xor(volatile a128 *a, a128 v, morder mo) {744a128 __tsan_atomic128_fetch_xor(volatile a128 *a, a128 v, int mo) {
709 ATOMIC_IMPL(FetchXor, a, v, mo);745 return AtomicImpl<OpFetchXor>(to_morder(mo), a, v);
710}746}
711#endif747# endif
712748
713SANITIZER_INTERFACE_ATTRIBUTE749SANITIZER_INTERFACE_ATTRIBUTE
714a8 __tsan_atomic8_fetch_nand(volatile a8 *a, a8 v, morder mo) {750a8 __tsan_atomic8_fetch_nand(volatile a8 *a, a8 v, int mo) {
715 ATOMIC_IMPL(FetchNand, a, v, mo);751 return AtomicImpl<OpFetchNand>(to_morder(mo), a, v);
716}752}
717753
718SANITIZER_INTERFACE_ATTRIBUTE754SANITIZER_INTERFACE_ATTRIBUTE
719a16 __tsan_atomic16_fetch_nand(volatile a16 *a, a16 v, morder mo) {755a16 __tsan_atomic16_fetch_nand(volatile a16 *a, a16 v, int mo) {
720 ATOMIC_IMPL(FetchNand, a, v, mo);756 return AtomicImpl<OpFetchNand>(to_morder(mo), a, v);
721}757}
722758
723SANITIZER_INTERFACE_ATTRIBUTE759SANITIZER_INTERFACE_ATTRIBUTE
724a32 __tsan_atomic32_fetch_nand(volatile a32 *a, a32 v, morder mo) {760a32 __tsan_atomic32_fetch_nand(volatile a32 *a, a32 v, int mo) {
725 ATOMIC_IMPL(FetchNand, a, v, mo);761 return AtomicImpl<OpFetchNand>(to_morder(mo), a, v);
726}762}
727763
728SANITIZER_INTERFACE_ATTRIBUTE764SANITIZER_INTERFACE_ATTRIBUTE
729a64 __tsan_atomic64_fetch_nand(volatile a64 *a, a64 v, morder mo) {765a64 __tsan_atomic64_fetch_nand(volatile a64 *a, a64 v, int mo) {
730 ATOMIC_IMPL(FetchNand, a, v, mo);766 return AtomicImpl<OpFetchNand>(to_morder(mo), a, v);
731}767}
732768
733#if __TSAN_HAS_INT128769# if __TSAN_HAS_INT128
734SANITIZER_INTERFACE_ATTRIBUTE770SANITIZER_INTERFACE_ATTRIBUTE
735a128 __tsan_atomic128_fetch_nand(volatile a128 *a, a128 v, morder mo) {771a128 __tsan_atomic128_fetch_nand(volatile a128 *a, a128 v, int mo) {
736 ATOMIC_IMPL(FetchNand, a, v, mo);772 return AtomicImpl<OpFetchNand>(to_morder(mo), a, v);
737}773}
738#endif774# endif
739775
740SANITIZER_INTERFACE_ATTRIBUTE776SANITIZER_INTERFACE_ATTRIBUTE
741int __tsan_atomic8_compare_exchange_strong(volatile a8 *a, a8 *c, a8 v,777int __tsan_atomic8_compare_exchange_strong(volatile a8 *a, a8 *c, a8 v, int mo,
742 morder mo, morder fmo) {778 int fmo) {
743 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);779 return AtomicImpl<OpCAS>(to_morder(mo), to_morder(fmo), a, c, v);
744}780}
745781
746SANITIZER_INTERFACE_ATTRIBUTE782SANITIZER_INTERFACE_ATTRIBUTE
747int __tsan_atomic16_compare_exchange_strong(volatile a16 *a, a16 *c, a16 v,783int __tsan_atomic16_compare_exchange_strong(volatile a16 *a, a16 *c, a16 v,
748 morder mo, morder fmo) {784 int mo, int fmo) {
749 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);785 return AtomicImpl<OpCAS>(to_morder(mo), to_morder(fmo), a, c, v);
750}786}
751787
752SANITIZER_INTERFACE_ATTRIBUTE788SANITIZER_INTERFACE_ATTRIBUTE
753int __tsan_atomic32_compare_exchange_strong(volatile a32 *a, a32 *c, a32 v,789int __tsan_atomic32_compare_exchange_strong(volatile a32 *a, a32 *c, a32 v,
754 morder mo, morder fmo) {790 int mo, int fmo) {
755 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);791 return AtomicImpl<OpCAS>(to_morder(mo), to_morder(fmo), a, c, v);
756}792}
757793
758SANITIZER_INTERFACE_ATTRIBUTE794SANITIZER_INTERFACE_ATTRIBUTE
759int __tsan_atomic64_compare_exchange_strong(volatile a64 *a, a64 *c, a64 v,795int __tsan_atomic64_compare_exchange_strong(volatile a64 *a, a64 *c, a64 v,
760 morder mo, morder fmo) {796 int mo, int fmo) {
761 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);797 return AtomicImpl<OpCAS>(to_morder(mo), to_morder(fmo), a, c, v);
762}798}
763799
764#if __TSAN_HAS_INT128800# if __TSAN_HAS_INT128
765SANITIZER_INTERFACE_ATTRIBUTE801SANITIZER_INTERFACE_ATTRIBUTE
766int __tsan_atomic128_compare_exchange_strong(volatile a128 *a, a128 *c, a128 v,802int __tsan_atomic128_compare_exchange_strong(volatile a128 *a, a128 *c, a128 v,
767 morder mo, morder fmo) {803 int mo, int fmo) {
768 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);804 return AtomicImpl<OpCAS>(to_morder(mo), to_morder(fmo), a, c, v);
769}805}
770#endif806# endif
771807
772SANITIZER_INTERFACE_ATTRIBUTE808SANITIZER_INTERFACE_ATTRIBUTE
773int __tsan_atomic8_compare_exchange_weak(volatile a8 *a, a8 *c, a8 v,809int __tsan_atomic8_compare_exchange_weak(volatile a8 *a, a8 *c, a8 v, int mo,
774 morder mo, morder fmo) {810 int fmo) {
775 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);811 return AtomicImpl<OpCAS>(to_morder(mo), to_morder(fmo), a, c, v);
776}812}
777813
778SANITIZER_INTERFACE_ATTRIBUTE814SANITIZER_INTERFACE_ATTRIBUTE
779int __tsan_atomic16_compare_exchange_weak(volatile a16 *a, a16 *c, a16 v,815int __tsan_atomic16_compare_exchange_weak(volatile a16 *a, a16 *c, a16 v,
780 morder mo, morder fmo) {816 int mo, int fmo) {
781 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);817 return AtomicImpl<OpCAS>(to_morder(mo), to_morder(fmo), a, c, v);
782}818}
783819
784SANITIZER_INTERFACE_ATTRIBUTE820SANITIZER_INTERFACE_ATTRIBUTE
785int __tsan_atomic32_compare_exchange_weak(volatile a32 *a, a32 *c, a32 v,821int __tsan_atomic32_compare_exchange_weak(volatile a32 *a, a32 *c, a32 v,
786 morder mo, morder fmo) {822 int mo, int fmo) {
787 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);823 return AtomicImpl<OpCAS>(to_morder(mo), to_morder(fmo), a, c, v);
788}824}
789825
790SANITIZER_INTERFACE_ATTRIBUTE826SANITIZER_INTERFACE_ATTRIBUTE
791int __tsan_atomic64_compare_exchange_weak(volatile a64 *a, a64 *c, a64 v,827int __tsan_atomic64_compare_exchange_weak(volatile a64 *a, a64 *c, a64 v,
792 morder mo, morder fmo) {828 int mo, int fmo) {
793 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);829 return AtomicImpl<OpCAS>(to_morder(mo), to_morder(fmo), a, c, v);
794}830}
795831
796#if __TSAN_HAS_INT128832# if __TSAN_HAS_INT128
797SANITIZER_INTERFACE_ATTRIBUTE833SANITIZER_INTERFACE_ATTRIBUTE
798int __tsan_atomic128_compare_exchange_weak(volatile a128 *a, a128 *c, a128 v,834int __tsan_atomic128_compare_exchange_weak(volatile a128 *a, a128 *c, a128 v,
799 morder mo, morder fmo) {835 int mo, int fmo) {
800 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);836 return AtomicImpl<OpCAS>(to_morder(mo), to_morder(fmo), a, c, v);
801}837}
802#endif838# endif
803839
804SANITIZER_INTERFACE_ATTRIBUTE840SANITIZER_INTERFACE_ATTRIBUTE
805a8 __tsan_atomic8_compare_exchange_val(volatile a8 *a, a8 c, a8 v,841a8 __tsan_atomic8_compare_exchange_val(volatile a8 *a, a8 c, a8 v, int mo,
806 morder mo, morder fmo) {842 int fmo) {
807 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);843 return AtomicImpl<OpCAS>(to_morder(mo), to_morder(fmo), a, c, v);
808}844}
809845
810SANITIZER_INTERFACE_ATTRIBUTE846SANITIZER_INTERFACE_ATTRIBUTE
811a16 __tsan_atomic16_compare_exchange_val(volatile a16 *a, a16 c, a16 v,847a16 __tsan_atomic16_compare_exchange_val(volatile a16 *a, a16 c, a16 v, int mo,
812 morder mo, morder fmo) {848 int fmo) {
813 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);849 return AtomicImpl<OpCAS>(to_morder(mo), to_morder(fmo), a, c, v);
814}850}
815851
816SANITIZER_INTERFACE_ATTRIBUTE852SANITIZER_INTERFACE_ATTRIBUTE
817a32 __tsan_atomic32_compare_exchange_val(volatile a32 *a, a32 c, a32 v,853a32 __tsan_atomic32_compare_exchange_val(volatile a32 *a, a32 c, a32 v, int mo,
818 morder mo, morder fmo) {854 int fmo) {
819 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);855 return AtomicImpl<OpCAS>(to_morder(mo), to_morder(fmo), a, c, v);
820}856}
821857
822SANITIZER_INTERFACE_ATTRIBUTE858SANITIZER_INTERFACE_ATTRIBUTE
823a64 __tsan_atomic64_compare_exchange_val(volatile a64 *a, a64 c, a64 v,859a64 __tsan_atomic64_compare_exchange_val(volatile a64 *a, a64 c, a64 v, int mo,
824 morder mo, morder fmo) {860 int fmo) {
825 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);861 return AtomicImpl<OpCAS>(to_morder(mo), to_morder(fmo), a, c, v);
826}862}
827863
828#if __TSAN_HAS_INT128864# if __TSAN_HAS_INT128
829SANITIZER_INTERFACE_ATTRIBUTE865SANITIZER_INTERFACE_ATTRIBUTE
830a128 __tsan_atomic128_compare_exchange_val(volatile a128 *a, a128 c, a128 v,866a128 __tsan_atomic128_compare_exchange_val(volatile a128 *a, a128 c, a128 v,
831 morder mo, morder fmo) {867 int mo, int fmo) {
832 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);868 return AtomicImpl<OpCAS>(to_morder(mo), to_morder(fmo), a, c, v);
833}869}
834#endif870# endif
835871
836SANITIZER_INTERFACE_ATTRIBUTE872SANITIZER_INTERFACE_ATTRIBUTE
837void __tsan_atomic_thread_fence(morder mo) { ATOMIC_IMPL(Fence, mo); }873void __tsan_atomic_thread_fence(int mo) {
874 return AtomicImpl<OpFence>(to_morder(mo));
875}
838876
839SANITIZER_INTERFACE_ATTRIBUTE877SANITIZER_INTERFACE_ATTRIBUTE
840void __tsan_atomic_signal_fence(morder mo) {878void __tsan_atomic_signal_fence(int mo) {}
841}
842} // extern "C"879} // extern "C"
843880
844#else // #if !SANITIZER_GO881#else // #if !SANITIZER_GO
845882
846// Go883// Go
847884
848# define ATOMIC(func, ...) \885template <class Op, class... Types>
849 if (thr->ignore_sync) { \886void AtomicGo(ThreadState *thr, uptr cpc, uptr pc, Types... args) {
850 NoTsanAtomic##func(__VA_ARGS__); \887 if (thr->ignore_sync) {
851 } else { \888 (void)Op::NoTsanAtomic(args...);
852 FuncEntry(thr, cpc); \889 } else {
853 Atomic##func(thr, pc, __VA_ARGS__); \890 FuncEntry(thr, cpc);
854 FuncExit(thr); \891 (void)Op::Atomic(thr, pc, args...);
855 }892 FuncExit(thr);
893 }
894}
856895
857# define ATOMIC_RET(func, ret, ...) \896template <class Op, class... Types>
858 if (thr->ignore_sync) { \897auto AtomicGoRet(ThreadState *thr, uptr cpc, uptr pc, Types... args) {
859 (ret) = NoTsanAtomic##func(__VA_ARGS__); \898 if (thr->ignore_sync) {
860 } else { \899 return Op::NoTsanAtomic(args...);
861 FuncEntry(thr, cpc); \900 } else {
862 (ret) = Atomic##func(thr, pc, __VA_ARGS__); \901 FuncEntry(thr, cpc);
863 FuncExit(thr); \902 auto ret = Op::Atomic(thr, pc, args...);
864 }903 FuncExit(thr);
904 return ret;
905 }
906}
865907
866extern "C" {908extern "C" {
867SANITIZER_INTERFACE_ATTRIBUTE909SANITIZER_INTERFACE_ATTRIBUTE
868void __tsan_go_atomic32_load(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {910void __tsan_go_atomic32_load(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
869 ATOMIC_RET(Load, *(a32*)(a+8), *(a32**)a, mo_acquire);911 *(a32 *)(a + 8) = AtomicGoRet<OpLoad>(thr, cpc, pc, mo_acquire, *(a32 **)a);
870}912}
871913
872SANITIZER_INTERFACE_ATTRIBUTE914SANITIZER_INTERFACE_ATTRIBUTE
873void __tsan_go_atomic64_load(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {915void __tsan_go_atomic64_load(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
874 ATOMIC_RET(Load, *(a64*)(a+8), *(a64**)a, mo_acquire);916 *(a64 *)(a + 8) = AtomicGoRet<OpLoad>(thr, cpc, pc, mo_acquire, *(a64 **)a);
875}917}
876918
877SANITIZER_INTERFACE_ATTRIBUTE919SANITIZER_INTERFACE_ATTRIBUTE
878void __tsan_go_atomic32_store(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {920void __tsan_go_atomic32_store(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
879 ATOMIC(Store, *(a32**)a, *(a32*)(a+8), mo_release);921 AtomicGo<OpStore>(thr, cpc, pc, mo_release, *(a32 **)a, *(a32 *)(a + 8));
880}922}
881923
882SANITIZER_INTERFACE_ATTRIBUTE924SANITIZER_INTERFACE_ATTRIBUTE
883void __tsan_go_atomic64_store(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {925void __tsan_go_atomic64_store(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
884 ATOMIC(Store, *(a64**)a, *(a64*)(a+8), mo_release);926 AtomicGo<OpStore>(thr, cpc, pc, mo_release, *(a64 **)a, *(a64 *)(a + 8));
885}927}
886928
887SANITIZER_INTERFACE_ATTRIBUTE929SANITIZER_INTERFACE_ATTRIBUTE
888void __tsan_go_atomic32_fetch_add(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {930void __tsan_go_atomic32_fetch_add(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
889 ATOMIC_RET(FetchAdd, *(a32*)(a+16), *(a32**)a, *(a32*)(a+8), mo_acq_rel);931 *(a32 *)(a + 16) = AtomicGoRet<OpFetchAdd>(thr, cpc, pc, mo_acq_rel,
932 *(a32 **)a, *(a32 *)(a + 8));
890}933}
891934
892SANITIZER_INTERFACE_ATTRIBUTE935SANITIZER_INTERFACE_ATTRIBUTE
893void __tsan_go_atomic64_fetch_add(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {936void __tsan_go_atomic64_fetch_add(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
894 ATOMIC_RET(FetchAdd, *(a64*)(a+16), *(a64**)a, *(a64*)(a+8), mo_acq_rel);937 *(a64 *)(a + 16) = AtomicGoRet<OpFetchAdd>(thr, cpc, pc, mo_acq_rel,
938 *(a64 **)a, *(a64 *)(a + 8));
895}939}
896940
897SANITIZER_INTERFACE_ATTRIBUTE941SANITIZER_INTERFACE_ATTRIBUTE
898void __tsan_go_atomic32_fetch_and(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {942void __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),943 *(a32 *)(a + 16) = AtomicGoRet<OpFetchAnd>(thr, cpc, pc, mo_acq_rel,
900 mo_acq_rel);944 *(a32 **)a, *(a32 *)(a + 8));
901}945}
902946
903SANITIZER_INTERFACE_ATTRIBUTE947SANITIZER_INTERFACE_ATTRIBUTE
904void __tsan_go_atomic64_fetch_and(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {948void __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),949 *(a64 *)(a + 16) = AtomicGoRet<OpFetchAnd>(thr, cpc, pc, mo_acq_rel,
906 mo_acq_rel);950 *(a64 **)a, *(a64 *)(a + 8));
907}951}
908952
909SANITIZER_INTERFACE_ATTRIBUTE953SANITIZER_INTERFACE_ATTRIBUTE
910void __tsan_go_atomic32_fetch_or(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {954void __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),955 *(a32 *)(a + 16) = AtomicGoRet<OpFetchOr>(thr, cpc, pc, mo_acq_rel,
912 mo_acq_rel);956 *(a32 **)a, *(a32 *)(a + 8));
913}957}
914958
915SANITIZER_INTERFACE_ATTRIBUTE959SANITIZER_INTERFACE_ATTRIBUTE
916void __tsan_go_atomic64_fetch_or(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {960void __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),961 *(a64 *)(a + 16) = AtomicGoRet<OpFetchOr>(thr, cpc, pc, mo_acq_rel,
918 mo_acq_rel);962 *(a64 **)a, *(a64 *)(a + 8));
919}963}
920964
921SANITIZER_INTERFACE_ATTRIBUTE965SANITIZER_INTERFACE_ATTRIBUTE
922void __tsan_go_atomic32_exchange(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {966void __tsan_go_atomic32_exchange(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
923 ATOMIC_RET(Exchange, *(a32*)(a+16), *(a32**)a, *(a32*)(a+8), mo_acq_rel);967 *(a32 *)(a + 16) = AtomicGoRet<OpExchange>(thr, cpc, pc, mo_acq_rel,
968 *(a32 **)a, *(a32 *)(a + 8));
924}969}
925970
926SANITIZER_INTERFACE_ATTRIBUTE971SANITIZER_INTERFACE_ATTRIBUTE
927void __tsan_go_atomic64_exchange(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {972void __tsan_go_atomic64_exchange(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
928 ATOMIC_RET(Exchange, *(a64*)(a+16), *(a64**)a, *(a64*)(a+8), mo_acq_rel);973 *(a64 *)(a + 16) = AtomicGoRet<OpExchange>(thr, cpc, pc, mo_acq_rel,
974 *(a64 **)a, *(a64 *)(a + 8));
929}975}
930976
931SANITIZER_INTERFACE_ATTRIBUTE977SANITIZER_INTERFACE_ATTRIBUTE
932void __tsan_go_atomic32_compare_exchange(978void __tsan_go_atomic32_compare_exchange(ThreadState *thr, uptr cpc, uptr pc,
933 ThreadState *thr, uptr cpc, uptr pc, u8 *a) {979 u8 *a) {
934 a32 cur = 0;980 a32 cmp = *(a32 *)(a + 8);
935 a32 cmp = *(a32*)(a+8);981 a32 cur = AtomicGoRet<OpCAS>(thr, cpc, pc, mo_acq_rel, mo_acquire, *(a32 **)a,
936 ATOMIC_RET(CAS, cur, *(a32**)a, cmp, *(a32*)(a+12), mo_acq_rel, mo_acquire);982 cmp, *(a32 *)(a + 12));
937 *(bool*)(a+16) = (cur == cmp);983 *(bool *)(a + 16) = (cur == cmp);
938}984}
939985
940SANITIZER_INTERFACE_ATTRIBUTE986SANITIZER_INTERFACE_ATTRIBUTE
941void __tsan_go_atomic64_compare_exchange(987void __tsan_go_atomic64_compare_exchange(ThreadState *thr, uptr cpc, uptr pc,
942 ThreadState *thr, uptr cpc, uptr pc, u8 *a) {988 u8 *a) {
943 a64 cur = 0;989 a64 cmp = *(a64 *)(a + 8);
944 a64 cmp = *(a64*)(a+8);990 a64 cur = AtomicGoRet<OpCAS>(thr, cpc, pc, mo_acq_rel, mo_acquire, *(a64 **)a,
945 ATOMIC_RET(CAS, cur, *(a64**)a, cmp, *(a64*)(a+16), mo_acq_rel, mo_acquire);991 cmp, *(a64 *)(a + 16));
946 *(bool*)(a+24) = (cur == cmp);992 *(bool *)(a + 24) = (cur == cmp);
947}993}
948} // extern "C"994} // extern "C"
949#endif // #if !SANITIZER_GO995#endif // #if !SANITIZER_GO
lib/tsan/tsan_mman.cpp+1-1
...@@ -252,7 +252,7 @@ void *user_reallocarray(ThreadState *thr, uptr pc, void *p, uptr size, uptr n) {...@@ -252,7 +252,7 @@ void *user_reallocarray(ThreadState *thr, uptr pc, void *p, uptr size, uptr n) {
252 if (AllocatorMayReturnNull())252 if (AllocatorMayReturnNull())
253 return SetErrnoOnNull(nullptr);253 return SetErrnoOnNull(nullptr);
254 GET_STACK_TRACE_FATAL(thr, pc);254 GET_STACK_TRACE_FATAL(thr, pc);
255 ReportReallocArrayOverflow(size, n, &stack);255 ReportReallocArrayOverflow(n, size, &stack);
256 }256 }
257 return user_realloc(thr, pc, p, size * n);257 return user_realloc(thr, pc, p, size * n);
258}258}
lib/tsan/tsan_platform_linux.cpp-1
...@@ -418,7 +418,6 @@ void InitializePlatform() {...@@ -418,7 +418,6 @@ void InitializePlatform() {
418 Die();418 Die();
419 }419 }
420420
421 InitTlsSize();
422#endif // !SANITIZER_GO421#endif // !SANITIZER_GO
423}422}
424423
lib/tsan/tsan_rtl.cpp+4-1
...@@ -673,7 +673,8 @@ void CheckUnwind() {...@@ -673,7 +673,8 @@ void CheckUnwind() {
673 thr->ignore_reads_and_writes++;673 thr->ignore_reads_and_writes++;
674 atomic_store_relaxed(&thr->in_signal_handler, 0);674 atomic_store_relaxed(&thr->in_signal_handler, 0);
675#endif675#endif
676 PrintCurrentStackSlow(StackTrace::GetCurrentPc());676 PrintCurrentStack(StackTrace::GetCurrentPc(),
677 common_flags()->fast_unwind_on_fatal);
677}678}
678679
679bool is_initialized;680bool is_initialized;
...@@ -806,6 +807,7 @@ int Finalize(ThreadState *thr) {...@@ -806,6 +807,7 @@ int Finalize(ThreadState *thr) {
806807
807#if !SANITIZER_GO808#if !SANITIZER_GO
808void ForkBefore(ThreadState* thr, uptr pc) SANITIZER_NO_THREAD_SAFETY_ANALYSIS {809void ForkBefore(ThreadState* thr, uptr pc) SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
810 VReport(2, "BeforeFork tid: %llu\n", GetTid());
809 GlobalProcessorLock();811 GlobalProcessorLock();
810 // Detaching from the slot makes OnUserFree skip writing to the shadow.812 // Detaching from the slot makes OnUserFree skip writing to the shadow.
811 // The slot will be locked so any attempts to use it will deadlock anyway.813 // The slot will be locked so any attempts to use it will deadlock anyway.
...@@ -847,6 +849,7 @@ static void ForkAfter(ThreadState* thr,...@@ -847,6 +849,7 @@ static void ForkAfter(ThreadState* thr,
847 SlotAttachAndLock(thr);849 SlotAttachAndLock(thr);
848 SlotUnlock(thr);850 SlotUnlock(thr);
849 GlobalProcessorUnlock();851 GlobalProcessorUnlock();
852 VReport(2, "AfterFork tid: %llu\n", GetTid());
850}853}
851854
852void ForkParentAfter(ThreadState* thr, uptr pc) { ForkAfter(thr, false); }855void ForkParentAfter(ThreadState* thr, uptr pc) { ForkAfter(thr, false); }
lib/tsan/tsan_rtl.h+1-1
...@@ -514,7 +514,7 @@ bool IsExpectedReport(uptr addr, uptr size);...@@ -514,7 +514,7 @@ bool IsExpectedReport(uptr addr, uptr size);
514StackID CurrentStackId(ThreadState *thr, uptr pc);514StackID CurrentStackId(ThreadState *thr, uptr pc);
515ReportStack *SymbolizeStackId(StackID stack_id);515ReportStack *SymbolizeStackId(StackID stack_id);
516void PrintCurrentStack(ThreadState *thr, uptr pc);516void PrintCurrentStack(ThreadState *thr, uptr pc);
517void PrintCurrentStackSlow(uptr pc); // uses libunwind517void PrintCurrentStack(uptr pc, bool fast); // may uses libunwind
518MBlock *JavaHeapBlock(uptr addr, uptr *start);518MBlock *JavaHeapBlock(uptr addr, uptr *start);
519519
520void Initialize(ThreadState *thr);520void Initialize(ThreadState *thr);
lib/tsan/tsan_rtl_report.cpp+5-5
...@@ -828,18 +828,18 @@ void PrintCurrentStack(ThreadState *thr, uptr pc) {...@@ -828,18 +828,18 @@ void PrintCurrentStack(ThreadState *thr, uptr pc) {
828 PrintStack(SymbolizeStack(trace));828 PrintStack(SymbolizeStack(trace));
829}829}
830830
831// Always inlining PrintCurrentStackSlow, because LocatePcInTrace assumes831// Always inlining PrintCurrentStack, because LocatePcInTrace assumes
832// __sanitizer_print_stack_trace exists in the actual unwinded stack, but832// __sanitizer_print_stack_trace exists in the actual unwinded stack, but
833// tail-call to PrintCurrentStackSlow breaks this assumption because833// tail-call to PrintCurrentStack breaks this assumption because
834// __sanitizer_print_stack_trace disappears after tail-call.834// __sanitizer_print_stack_trace disappears after tail-call.
835// However, this solution is not reliable enough, please see dvyukov's comment835// However, this solution is not reliable enough, please see dvyukov's comment
836// http://reviews.llvm.org/D19148#406208836// http://reviews.llvm.org/D19148#406208
837// Also see PR27280 comment 2 and 3 for breaking examples and analysis.837// Also see PR27280 comment 2 and 3 for breaking examples and analysis.
838ALWAYS_INLINE USED void PrintCurrentStackSlow(uptr pc) {838ALWAYS_INLINE USED void PrintCurrentStack(uptr pc, bool fast) {
839#if !SANITIZER_GO839#if !SANITIZER_GO
840 uptr bp = GET_CURRENT_FRAME();840 uptr bp = GET_CURRENT_FRAME();
841 auto *ptrace = New<BufferedStackTrace>();841 auto *ptrace = New<BufferedStackTrace>();
842 ptrace->Unwind(pc, bp, nullptr, false);842 ptrace->Unwind(pc, bp, nullptr, fast);
843843
844 for (uptr i = 0; i < ptrace->size / 2; i++) {844 for (uptr i = 0; i < ptrace->size / 2; i++) {
845 uptr tmp = ptrace->trace_buffer[i];845 uptr tmp = ptrace->trace_buffer[i];
...@@ -857,6 +857,6 @@ using namespace __tsan;...@@ -857,6 +857,6 @@ using namespace __tsan;
857extern "C" {857extern "C" {
858SANITIZER_INTERFACE_ATTRIBUTE858SANITIZER_INTERFACE_ATTRIBUTE
859void __sanitizer_print_stack_trace() {859void __sanitizer_print_stack_trace() {
860 PrintCurrentStackSlow(StackTrace::GetCurrentPc());860 PrintCurrentStack(StackTrace::GetCurrentPc(), false);
861}861}
862} // extern "C"862} // extern "C"
lib/tsan/tsan_rtl_thread.cpp+6-4
...@@ -165,14 +165,16 @@ void ThreadStart(ThreadState *thr, Tid tid, tid_t os_id,...@@ -165,14 +165,16 @@ void ThreadStart(ThreadState *thr, Tid tid, tid_t os_id,
165#endif165#endif
166166
167 uptr stk_addr = 0;167 uptr stk_addr = 0;
168 uptr stk_size = 0;168 uptr stk_end = 0;
169 uptr tls_addr = 0;169 uptr tls_addr = 0;
170 uptr tls_size = 0;170 uptr tls_end = 0;
171#if !SANITIZER_GO171#if !SANITIZER_GO
172 if (thread_type != ThreadType::Fiber)172 if (thread_type != ThreadType::Fiber)
173 GetThreadStackAndTls(tid == kMainTid, &stk_addr, &stk_size, &tls_addr,173 GetThreadStackAndTls(tid == kMainTid, &stk_addr, &stk_end, &tls_addr,
174 &tls_size);174 &tls_end);
175#endif175#endif
176 uptr stk_size = stk_end - stk_addr;
177 uptr tls_size = tls_end - tls_addr;
176 thr->stk_addr = stk_addr;178 thr->stk_addr = stk_addr;
177 thr->stk_size = stk_size;179 thr->stk_size = stk_size;
178 thr->tls_addr = tls_addr;180 thr->tls_addr = tls_addr;
lib/tsan/tsan_spinlock_defs_mac.h deleted-45
...@@ -1,45 +0,0 @@
1//===-- tsan_spinlock_defs_mac.h -------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file is a part of ThreadSanitizer (TSan), a race detector.
10//
11// Mac-specific forward-declared function defintions that may be
12// deprecated in later versions of the OS.
13// These are needed for interceptors.
14//
15//===----------------------------------------------------------------------===//
16
17#if SANITIZER_APPLE
18
19#ifndef TSAN_SPINLOCK_DEFS_MAC_H
20#define TSAN_SPINLOCK_DEFS_MAC_H
21
22#include <stdint.h>
23
24extern "C" {
25
26/*
27Provides forward declarations related to OSSpinLocks on Darwin. These functions are
28deprecated on macOS version 10.12 and later,
29and are no longer included in the system headers.
30
31However, the symbols are still available on the system, so we provide these forward
32declarations to prevent compilation errors in tsan_interceptors_mac.cpp, which
33references these functions when defining TSAN interceptor functions.
34*/
35
36typedef int32_t OSSpinLock;
37
38void OSSpinLockLock(volatile OSSpinLock *__lock);
39void OSSpinLockUnlock(volatile OSSpinLock *__lock);
40bool OSSpinLockTry(volatile OSSpinLock *__lock);
41
42}
43
44#endif //TSAN_SPINLOCK_DEFS_MAC_H
45#endif // SANITIZER_APPLE
src/libtsan.zig+2-6
...@@ -410,9 +410,6 @@ const sanitizer_common_sources = [_][]const u8{...@@ -410,9 +410,6 @@ const sanitizer_common_sources = [_][]const u8{
410 "sanitizer_allocator.cpp",410 "sanitizer_allocator.cpp",
411 "sanitizer_chained_origin_depot.cpp",411 "sanitizer_chained_origin_depot.cpp",
412 "sanitizer_common.cpp",412 "sanitizer_common.cpp",
413 "sanitizer_coverage_win_dll_thunk.cpp",
414 "sanitizer_coverage_win_dynamic_runtime_thunk.cpp",
415 "sanitizer_coverage_win_weak_interception.cpp",
416 "sanitizer_deadlock_detector1.cpp",413 "sanitizer_deadlock_detector1.cpp",
417 "sanitizer_deadlock_detector2.cpp",414 "sanitizer_deadlock_detector2.cpp",
418 "sanitizer_errno.cpp",415 "sanitizer_errno.cpp",
...@@ -452,9 +449,7 @@ const sanitizer_common_sources = [_][]const u8{...@@ -452,9 +449,7 @@ const sanitizer_common_sources = [_][]const u8{
452 "sanitizer_tls_get_addr.cpp",449 "sanitizer_tls_get_addr.cpp",
453 "sanitizer_type_traits.cpp",450 "sanitizer_type_traits.cpp",
454 "sanitizer_win.cpp",451 "sanitizer_win.cpp",
455 "sanitizer_win_dll_thunk.cpp",452 "sanitizer_win_interception.cpp",
456 "sanitizer_win_dynamic_runtime_thunk.cpp",
457 "sanitizer_win_weak_interception.cpp",
458};453};
459454
460const sanitizer_nolibc_sources = [_][]const u8{455const sanitizer_nolibc_sources = [_][]const u8{
...@@ -490,6 +485,7 @@ const sanitizer_symbolizer_sources = [_][]const u8{...@@ -490,6 +485,7 @@ const sanitizer_symbolizer_sources = [_][]const u8{
490 "sanitizer_symbolizer_report.cpp",485 "sanitizer_symbolizer_report.cpp",
491 "sanitizer_symbolizer_report_fuchsia.cpp",486 "sanitizer_symbolizer_report_fuchsia.cpp",
492 "sanitizer_symbolizer_win.cpp",487 "sanitizer_symbolizer_win.cpp",
488 "sanitizer_thread_history.cpp",
493 "sanitizer_unwind_linux_libcdep.cpp",489 "sanitizer_unwind_linux_libcdep.cpp",
494 "sanitizer_unwind_fuchsia.cpp",490 "sanitizer_unwind_fuchsia.cpp",
495 "sanitizer_unwind_win.cpp",491 "sanitizer_unwind_win.cpp",