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 @@
290290 CFI_END
291291#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
293305#endif // COMPILERRT_ASSEMBLY_H
lib/tsan/interception/interception.h+14-11
......@@ -25,8 +25,19 @@
2525
2626// These typedefs should be used only in the interceptor definitions to replace
2727// the standard system types (e.g. SSIZE_T instead of ssize_t)
28typedef __sanitizer::uptr SIZE_T;
29typedef __sanitizer::sptr SSIZE_T;
28// On Windows the system headers (basetsd.h) provide a conflicting definition
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
3041typedef __sanitizer::sptr PTRDIFF_T;
3142typedef __sanitizer::s64 INTMAX_T;
3243typedef __sanitizer::u64 UINTMAX_T;
......@@ -338,16 +349,8 @@ const interpose_substitution substitution_##func_name[] \
338349#endif
339350
340351// ISO C++ forbids casting between pointer-to-function and pointer-to-object,
341// so we use casting via an integral type __interception::uptr,
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.
352// so we use casts via uintptr_t (the local __sanitizer::uptr equivalent).
345353namespace __interception {
346#if defined(_WIN64)
347typedef unsigned long long uptr;
348#else
349typedef unsigned long uptr;
350#endif // _WIN64
351354
352355#if defined(__ELF__) && !SANITIZER_FUCHSIA
353356// The use of interceptors makes many sanitizers unusable for static linking.
lib/tsan/interception/interception_type_test.cpp+19-12
......@@ -12,28 +12,35 @@
1212//===----------------------------------------------------------------------===//
1313
1414#include "interception.h"
15#include "sanitizer_common/sanitizer_type_traits.h"
1516
16#if SANITIZER_LINUX || SANITIZER_APPLE
17
18#include <sys/types.h>
17#if __has_include(<sys/types.h>)
18# include <sys/types.h>
19#endif
1920#include <stddef.h>
2021#include <stdint.h>
2122
22COMPILER_CHECK(sizeof(::SIZE_T) == sizeof(size_t));
23COMPILER_CHECK(sizeof(::SSIZE_T) == sizeof(ssize_t));
24COMPILER_CHECK(sizeof(::PTRDIFF_T) == sizeof(ptrdiff_t));
23COMPILER_CHECK((__sanitizer::is_same<__sanitizer::uptr, ::uintptr_t>::value));
24COMPILER_CHECK((__sanitizer::is_same<__sanitizer::sptr, ::intptr_t>::value));
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)
2533COMPILER_CHECK(sizeof(::INTMAX_T) == sizeof(intmax_t));
34COMPILER_CHECK(sizeof(::UINTMAX_T) == sizeof(uintmax_t));
2635
27# if SANITIZER_GLIBC || SANITIZER_ANDROID
36#if SANITIZER_GLIBC || SANITIZER_ANDROID
2837COMPILER_CHECK(sizeof(::OFF64_T) == sizeof(off64_t));
29# endif
38#endif
3039
3140// The following are the cases when pread (and friends) is used instead of
3241// pread64. In those cases we need OFF_T to match off_t. We don't care about the
3342// rest (they depend on _FILE_OFFSET_BITS setting when building an application).
34# if SANITIZER_ANDROID || !defined _FILE_OFFSET_BITS || \
35 _FILE_OFFSET_BITS != 64
43#if !SANITIZER_WINDOWS && (SANITIZER_ANDROID || !defined _FILE_OFFSET_BITS || \
44 _FILE_OFFSET_BITS != 64)
3645COMPILER_CHECK(sizeof(::OFF_T) == sizeof(off_t));
37# endif
38
3946#endif
lib/tsan/interception/interception_win.cpp+364-68
......@@ -27,7 +27,7 @@
2727//
2828// 1) Detour
2929//
30// The Detour hooking technique is assuming the presence of an header with
30// The Detour hooking technique is assuming the presence of a header with
3131// padding and an overridable 2-bytes nop instruction (mov edi, edi). The
3232// nop instruction can safely be replaced by a 2-bytes jump without any need
3333// to save the instruction. A jump to the target is encoded in the function
......@@ -47,7 +47,7 @@
4747//
4848// func: jmp <label> --> func: jmp <hook>
4949//
50// On an 64-bit architecture, a trampoline is inserted.
50// On a 64-bit architecture, a trampoline is inserted.
5151//
5252// func: jmp <label> --> func: jmp <tramp>
5353// [...]
......@@ -60,7 +60,7 @@
6060//
6161// 3) HotPatch
6262//
63// The HotPatch hooking is assuming the presence of an header with padding
63// The HotPatch hooking is assuming the presence of a header with padding
6464// and a first instruction with at least 2-bytes.
6565//
6666// The reason to enforce the 2-bytes limitation is to provide the minimal
......@@ -80,7 +80,7 @@
8080// real: <instr>
8181// jmp <body>
8282//
83// On an 64-bit architecture:
83// On a 64-bit architecture:
8484//
8585// head: 6 x nop head: jmp QWORD [addr1]
8686// func: <instr> --> func: jmp short <head>
......@@ -110,7 +110,7 @@
110110// <instr>
111111// jmp <body>
112112//
113// On an 64-bit architecture:
113// On a 64-bit architecture:
114114//
115115// func: <instr> --> func: jmp QWORD [addr1]
116116// <instr>
......@@ -130,6 +130,7 @@
130130#include "sanitizer_common/sanitizer_platform.h"
131131#define WIN32_LEAN_AND_MEAN
132132#include <windows.h>
133#include <psapi.h>
133134
134135namespace __interception {
135136
......@@ -186,8 +187,12 @@ static uptr GetMmapGranularity() {
186187 return si.dwAllocationGranularity;
187188}
188189
190UNUSED static uptr RoundDownTo(uptr size, uptr boundary) {
191 return size & ~(boundary - 1);
192}
193
189194UNUSED static uptr RoundUpTo(uptr size, uptr boundary) {
190 return (size + boundary - 1) & ~(boundary - 1);
195 return RoundDownTo(size + boundary - 1, boundary);
191196}
192197
193198// FIXME: internal_str* and internal_mem* functions should be moved from the
......@@ -208,6 +213,18 @@ static char* _strchr(char* str, char c) {
208213 return nullptr;
209214}
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
211228static void _memset(void *p, int value, size_t sz) {
212229 for (size_t i = 0; i < sz; ++i)
213230 ((char*)p)[i] = (char)value;
......@@ -284,8 +301,11 @@ static void WriteJumpInstruction(uptr from, uptr target) {
284301
285302static void WriteShortJumpInstruction(uptr from, uptr target) {
286303 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);
288307 InterceptionFailed();
308 }
289309 *(u8*)from = 0xEB;
290310 *(u8*)(from + 1) = (u8)offset;
291311}
......@@ -339,32 +359,78 @@ struct TrampolineMemoryRegion {
339359 uptr max_size;
340360};
341361
342UNUSED static const uptr kTrampolineScanLimitRange = 1ull << 31; // 2 gig
362UNUSED static const uptr kTrampolineRangeLimit = 1ull << 31; // 2 gig
343363static const int kMaxTrampolineRegion = 1024;
344364static TrampolineMemoryRegion TrampolineRegions[kMaxTrampolineRegion];
345365
346static void *AllocateTrampolineRegion(uptr image_address, size_t granularity) {
347#if SANITIZER_WINDOWS64
348 uptr address = image_address;
349 uptr scanned = 0;
350 while (scanned < kTrampolineScanLimitRange) {
366static void *AllocateTrampolineRegion(uptr min_addr, uptr max_addr,
367 uptr func_addr, size_t granularity) {
368# if SANITIZER_WINDOWS64
369 // Clamp {min,max}_addr to the accessible address space.
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
351400 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);
353406 return nullptr;
407 }
354408
355 // Check whether a region can be allocated at |address|.
409 // Check whether a region can be allocated at |addr|.
356410 if (info.State == MEM_FREE && info.RegionSize >= granularity) {
357 void *page = ::VirtualAlloc((void*)RoundUpTo(address, granularity),
358 granularity,
359 MEM_RESERVE | MEM_COMMIT,
360 PAGE_EXECUTE_READWRITE);
411 void *page =
412 ::VirtualAlloc((void *)addr, granularity, MEM_RESERVE | MEM_COMMIT,
413 PAGE_EXECUTE_READWRITE);
414 if (page == nullptr)
415 ReportError(
416 "interception_win: VirtualAlloc in AllocateTrampolineRegion failed "
417 "for %p\n",
418 (void *)addr);
361419 return page;
362420 }
363421
364 // Move to the next region.
365 address = (uptr)info.BaseAddress + info.RegionSize;
366 scanned += info.RegionSize;
422 if (addr == lo_addr)
423 lo_addr =
424 RoundDownTo((uptr)info.AllocationBase - granularity, granularity);
425 if (addr == hi_addr)
426 hi_addr =
427 RoundUpTo((uptr)info.BaseAddress + info.RegionSize, granularity);
367428 }
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);
368434 return nullptr;
369435#else
370436 return ::VirtualAlloc(nullptr,
......@@ -385,15 +451,51 @@ void TestOnlyReleaseTrampolineRegions() {
385451 }
386452}
387453
388static uptr AllocateMemoryForTrampoline(uptr image_address, size_t size) {
389 // Find a region within 2G with enough space to allocate |size| bytes.
454static uptr AllocateMemoryForTrampoline(uptr func_address, size_t size) {
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.
390491 TrampolineMemoryRegion *region = nullptr;
391492 for (size_t bucket = 0; bucket < kMaxTrampolineRegion; ++bucket) {
392493 TrampolineMemoryRegion* current = &TrampolineRegions[bucket];
393494 if (current->content == 0) {
394495 // No valid region found, allocate a new region.
395496 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);
397499 if (content == nullptr)
398500 return 0U;
399501
......@@ -403,13 +505,9 @@ static uptr AllocateMemoryForTrampoline(uptr image_address, size_t size) {
403505 region = current;
404506 break;
405507 } else if (current->max_size - current->allocated_size > size) {
406#if SANITIZER_WINDOWS64
407 // In 64-bits, the memory space must be allocated within 2G boundary.
408 uptr next_address = current->content + current->allocated_size;
409 if (next_address < image_address ||
410 next_address - image_address >= 0x7FFF0000)
411 continue;
412#endif
508 uptr next_address = current->content + current->allocated_size;
509 if (next_address < min_addr || next_address > max_addr)
510 continue;
413511 // The space can be allocated in the current region.
414512 region = current;
415513 break;
......@@ -458,6 +556,10 @@ static const u8 kPrologueWithShortJump2[] = {
458556
459557// Returns 0 on error.
460558static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
559 if (rel_offset) {
560 *rel_offset = 0;
561 }
562
461563#if SANITIZER_ARM64
462564 // An ARM64 instruction is 4 bytes long.
463565 return 4;
......@@ -497,8 +599,14 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
497599 case 0x6A: // 6A XX = push XX
498600 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
500607 case 0xb8: // b8 XX XX XX XX : mov eax, XX XX XX XX
501608 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
502610 return 5;
503611
504612 // Cannot overwrite control-instruction. Return 0 to indicate failure.
......@@ -529,19 +637,43 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
529637 case 0xFF8B: // 8B FF : mov edi, edi
530638 case 0xEC8B: // 8B EC : mov ebp, esp
531639 case 0xc889: // 89 C8 : mov eax, ecx
640 case 0xD189: // 89 D1 : mov ecx, edx
532641 case 0xE589: // 89 E5 : mov ebp, esp
533642 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
534646 case 0xC033: // 33 C0 : xor eax, eax
535647 case 0xC933: // 33 C9 : xor ecx, ecx
536648 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
537653 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
539668 // 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]
541670 return 0;
542671 }
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;
545677 case 0x24A48D: // 8D A4 24 XX XX XX XX : lea esp, [esp + XX XX XX XX]
546678 return 7;
547679 }
......@@ -556,6 +688,21 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
556688 case 0xA1: // A1 XX XX XX XX XX XX XX XX :
557689 // movabs eax, dword ptr ds:[XXXXXXXX]
558690 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
560707 case 0x83:
561708 const u8 next_byte = *(u8*)(address + 1);
......@@ -584,55 +731,155 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
584731 case 0x018a: // mov al, byte ptr [rcx]
585732 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
587742 case 0x058A: // 8A 05 XX XX XX XX : mov al, byte ptr [XX XX XX XX]
588743 case 0x058B: // 8B 05 XX XX XX XX : mov eax, dword ptr [XX XX XX XX]
589744 if (rel_offset)
590745 *rel_offset = 2;
746 case 0xB841: // 41 B8 XX XX XX XX : mov r8d, XX XX XX XX
591747 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;
592756 }
593757
594 switch (0x00FFFFFF & *(u32*)address) {
595 case 0xe58948: // 48 8b c4 : mov rbp, rsp
596 case 0xc18b48: // 48 8b c1 : mov rax, rcx
597 case 0xc48b48: // 48 8b c4 : mov rax, rsp
598 case 0xd9f748: // 48 f7 d9 : neg rcx
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
758 switch (0x00FFFFFF & *(u32 *)address) {
759 case 0x10b70f: // 0f b7 10 : movzx edx, WORD PTR [rax]
760 case 0xc00b4d: // 4d 0b c0 : or r8, r8
761 case 0xc03345: // 45 33 c0 : xor r8d, r8d
762 case 0xc08548: // 48 85 c0 : test rax, rax
603763 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]
604776 case 0xc2b60f: // 0f b6 c2 : movzx eax, dl
605 case 0xc03345: // 45 33 c0 : xor r8d, r8d
777 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
606790 case 0xc93345: // 45 33 c9 : xor r9d, r9d
607 case 0xdb3345: // 45 33 DB : xor r11d, r11d
608 case 0xd98b4c: // 4c 8b d9 : mov r11, rcx
609 case 0xd28b4c: // 4c 8b d2 : mov r10, rdx
610 case 0xc98b4c: // 4C 8B C9 : mov r9, rcx
611 case 0xc18b4c: // 4C 8B C1 : mov r8, rcx
612 case 0xd2b60f: // 0f b6 d2 : movzx edx, dl
791 case 0xc98548: // 48 85 c9 : test rcx, rcx
792 case 0xc9854d: // 4d 85 c9 : test r9, r9
793 case 0xc98b4c: // 4c 8b c9 : mov r9, rcx
794 case 0xd12948: // 48 29 d1 : sub rcx, rdx
613795 case 0xca2b48: // 48 2b ca : sub rcx, rdx
614796 case 0xca3b48: // 48 3b ca : cmp rcx, rdx
615 case 0x10b70f: // 0f b7 10 : movzx edx, WORD PTR [rax]
616 case 0xc00b4d: // 3d 0b c0 : or r8, r8
617 case 0xc08b41: // 41 8b c0 : mov eax, r8d
797 case 0xd12b48: // 48 2b d1 : sub rdx, rcx
618798 case 0xd18b48: // 48 8b d1 : mov rdx, rcx
619 case 0xdc8b4c: // 4c 8b dc : mov r11, rsp
620799 case 0xd18b4c: // 4c 8b d1 : mov r10, rcx
621 case 0xE0E483: // 83 E4 E0 : and esp, 0xFFFFFFE0
800 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
622834 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
624839 case 0xec8348: // 48 83 ec XX : sub rsp, XX
625840 case 0xf88349: // 49 83 f8 XX : cmp r8, XX
626 case 0x588948: // 48 89 58 XX : mov QWORD PTR[rax + XX], rbx
841 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
627845 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
629859 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
630861 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
632875 case 0x058b48: // 48 8b 05 XX XX XX XX :
633876 // mov rax, QWORD PTR [rip + XXXXXXXX]
634877 case 0x058d48: // 48 8d 05 XX XX XX XX :
635878 // 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
636883 case 0x25ff48: // 48 ff 25 XX XX XX XX :
637884 // rex.W jmp QWORD PTR [rip + XXXXXXXX]
638885 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) {
644891 case 0x2444c7: // C7 44 24 XX YY YY YY YY
645892 // mov dword ptr [rsp + XX], YYYYYYYY
646893 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;
647898 }
648899
649900 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;
650907 case 0x24448b48: // 48 8b 44 24 XX : mov rax, QWORD ptr [rsp + XX]
651908 case 0x246c8948: // 48 89 6C 24 XX : mov QWORD ptr [rsp + XX], rbp
652909 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) {
656913 case 0x24548948: // 48 89 54 24 XX : mov QWORD PTR [rsp + XX], rdx
657914 case 0x244c894c: // 4c 89 4c 24 XX : mov QWORD PTR [rsp + XX], r9
658915 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]
659919 return 5;
660 case 0x24648348: // 48 83 64 24 XX : and QWORD PTR [rsp + XX], YY
920 case 0x24648348: // 48 83 64 24 XX YY : and QWORD PTR [rsp + XX], YY
661921 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;
662929 }
663930
664931#else
......@@ -671,11 +938,10 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
671938 case 0x458B: // 8B 45 XX : mov eax, dword ptr [ebp + XX]
672939 case 0x5D8B: // 8B 5D XX : mov ebx, dword ptr [ebp + XX]
673940 case 0x7D8B: // 8B 7D XX : mov edi, dword ptr [ebp + XX]
674 case 0xEC83: // 83 EC XX : sub esp, XX
941 case 0x758B: // 8B 75 XX : mov esi, dword ptr [ebp + XX]
675942 case 0x75FF: // FF 75 XX : push dword ptr [ebp + XX]
676943 return 3;
677944 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]
679945 return 6;
680946 case 0x3D83: // 83 3D XX YY ZZ WW TT : cmp TT, WWZZYYXX
681947 return 7;
......@@ -718,6 +984,10 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
718984 return 0;
719985}
720986
987size_t TestOnlyGetInstructionSize(uptr address, size_t *rel_offset) {
988 return GetInstructionSize(address, rel_offset);
989}
990
721991// Returns 0 on error.
722992static size_t RoundUpToInstrBoundary(size_t size, uptr address) {
723993 size_t cursor = 0;
......@@ -745,8 +1015,14 @@ static bool CopyInstructions(uptr to, uptr from, size_t size) {
7451015 // this will be untrue if relocated_offset \notin [-2**31, 2**31)
7461016 s64 delta = to - from;
7471017 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);
7491024 return false;
1025 }
7501026# else
7511027 // on 32-bit, the relative offset will always be correct
7521028 s32 delta = to - from;
......@@ -969,8 +1245,7 @@ static void **InterestingDLLsAvailable() {
9691245 "libc++.dll", // libc++
9701246 "libunwind.dll", // libunwind
9711247# endif
972 // NTDLL should go last as it exports some functions that we should
973 // override in the CRT [presumably only used internally].
1248 // NTDLL must go last as it gets special treatment in OverrideFunction.
9741249 "ntdll.dll",
9751250 NULL
9761251 };
......@@ -1027,7 +1302,7 @@ uptr InternalGetProcAddress(void *module, const char *func_name) {
10271302
10281303 for (DWORD i = 0; i < exports->NumberOfNames; i++) {
10291304 RVAPtr<char> name(module, names[i]);
1030 if (!strcmp(func_name, name)) {
1305 if (!_strcmp(func_name, name)) {
10311306 DWORD index = ordinals[i];
10321307 RVAPtr<char> func(module, functions[index]);
10331308
......@@ -1040,19 +1315,27 @@ uptr InternalGetProcAddress(void *module, const char *func_name) {
10401315 // exported directory.
10411316 char function_name[256];
10421317 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);
10441320 InterceptionFailed();
1321 }
10451322
10461323 _memcpy(function_name, func, funtion_name_length);
10471324 function_name[funtion_name_length] = '\0';
10481325 char* separator = _strchr(function_name, '.');
1049 if (!separator)
1326 if (!separator) {
1327 ReportError("interception_win: no separator in '%s'\n",
1328 function_name);
10501329 InterceptionFailed();
1330 }
10511331 *separator = '\0';
10521332
10531333 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);
10551337 InterceptionFailed();
1338 }
10561339 return InternalGetProcAddress(redirected_module, separator + 1);
10571340 }
10581341
......@@ -1065,9 +1348,22 @@ uptr InternalGetProcAddress(void *module, const char *func_name) {
10651348
10661349bool OverrideFunction(
10671350 const char *func_name, uptr new_func, uptr *orig_old_func) {
1351 static const char *kNtDllIgnore[] = {
1352 "memcmp", "memcpy", "memmove", "memset"
1353 };
1354
10681355 bool hooked = false;
10691356 void **DLLs = InterestingDLLsAvailable();
10701357 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
10711367 uptr func_addr = InternalGetProcAddress(DLLs[i], func_name);
10721368 if (func_addr &&
10731369 OverrideFunction(func_addr, new_func, orig_old_func)) {
......@@ -1121,7 +1417,7 @@ bool OverrideImportedFunction(const char *module_to_patch,
11211417 RVAPtr<IMAGE_IMPORT_BY_NAME> import_by_name(
11221418 module, name_table->u1.ForwarderString);
11231419 const char *funcname = &import_by_name->Name[0];
1124 if (strcmp(funcname, function_name) == 0)
1420 if (_strcmp(funcname, function_name) == 0)
11251421 break;
11261422 }
11271423 }
......@@ -1144,4 +1440,4 @@ bool OverrideImportedFunction(const char *module_to_patch,
11441440
11451441} // namespace __interception
11461442
1147#endif // SANITIZER_APPLE
1443#endif // SANITIZER_WINDOWS
lib/tsan/interception/interception_win.h+3
......@@ -63,6 +63,9 @@ bool OverrideFunctionWithTrampoline(
6363// Exposed for unittests
6464void TestOnlyReleaseTrampolineRegions();
6565
66// Exposed for unittests
67SIZE_T TestOnlyGetInstructionSize(uptr address, SIZE_T *rel_offset);
68
6669} // namespace __interception
6770
6871#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,
5959
6060static void *RawInternalRealloc(void *ptr, uptr size,
6161 InternalAllocatorCache *cache) {
62 uptr alignment = 8;
62 constexpr usize alignment = Max<usize>(8, sizeof(void *));
6363 if (cache == 0) {
6464 SpinMutexLock l(&internal_allocator_cache_mu);
6565 return internal_allocator()->Reallocate(&internal_allocator_cache, ptr,
......@@ -137,7 +137,8 @@ void InternalAllocatorUnlock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
137137}
138138
139139// LowLevelAllocator
140constexpr uptr kLowLevelAllocatorDefaultAlignment = 8;
140constexpr usize kLowLevelAllocatorDefaultAlignment =
141 Max<usize>(8, sizeof(void *));
141142constexpr uptr kMinNumPagesRounded = 16;
142143constexpr uptr kMinRoundedSize = 65536;
143144static uptr low_level_alloc_min_alignment = kLowLevelAllocatorDefaultAlignment;
lib/tsan/sanitizer_common/sanitizer_allocator_dlsym.h+18-9
......@@ -15,6 +15,8 @@
1515#define SANITIZER_ALLOCATOR_DLSYM_H
1616
1717#include "sanitizer_allocator_internal.h"
18#include "sanitizer_common/sanitizer_allocator_checks.h"
19#include "sanitizer_common/sanitizer_internal_defs.h"
1820
1921namespace __sanitizer {
2022
......@@ -31,24 +33,22 @@ struct DlSymAllocator {
3133 UNLIKELY(internal_allocator()->FromPrimary(ptr));
3234 }
3335
34 static void *Allocate(uptr size_in_bytes) {
35 void *ptr = InternalAlloc(size_in_bytes, nullptr, kWordSize);
36 static void *Allocate(uptr size_in_bytes, uptr align = kWordSize) {
37 void *ptr = InternalAlloc(size_in_bytes, nullptr, align);
3638 CHECK(internal_allocator()->FromPrimary(ptr));
37 Details::OnAllocate(ptr,
38 internal_allocator()->GetActuallyAllocatedSize(ptr));
39 Details::OnAllocate(ptr, GetSize(ptr));
3940 return ptr;
4041 }
4142
42 static void *Callocate(SIZE_T nmemb, SIZE_T size) {
43 static void *Callocate(usize nmemb, usize size) {
4344 void *ptr = InternalCalloc(nmemb, size);
4445 CHECK(internal_allocator()->FromPrimary(ptr));
45 Details::OnAllocate(ptr,
46 internal_allocator()->GetActuallyAllocatedSize(ptr));
46 Details::OnAllocate(ptr, GetSize(ptr));
4747 return ptr;
4848 }
4949
5050 static void Free(void *ptr) {
51 uptr size = internal_allocator()->GetActuallyAllocatedSize(ptr);
51 uptr size = GetSize(ptr);
5252 Details::OnFree(ptr, size);
5353 InternalFree(ptr);
5454 }
......@@ -61,7 +61,7 @@ struct DlSymAllocator {
6161 Free(ptr);
6262 return nullptr;
6363 }
64 uptr size = internal_allocator()->GetActuallyAllocatedSize(ptr);
64 uptr size = GetSize(ptr);
6565 uptr memcpy_size = Min(new_size, size);
6666 void *new_ptr = Allocate(new_size);
6767 if (new_ptr)
......@@ -70,6 +70,15 @@ struct DlSymAllocator {
7070 return new_ptr;
7171 }
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
7382 static void OnAllocate(const void *ptr, uptr size) {}
7483 static void OnFree(const void *ptr, uptr size) {}
7584};
lib/tsan/sanitizer_common/sanitizer_allocator_primary64.h+7-5
......@@ -185,9 +185,10 @@ class SizeClassAllocator64 {
185185 // recoverable.
186186 if (UNLIKELY(!EnsureFreeArraySpace(region, region_beg,
187187 new_num_freed_chunks))) {
188 Report("FATAL: Internal error: %s's allocator exhausted the free list "
189 "space for size class %zd (%zd bytes).\n", SanitizerToolName,
190 class_id, ClassIdToSize(class_id));
188 Report(
189 "FATAL: Internal error: %s's allocator exhausted the free list "
190 "space for size class %zu (%zu bytes).\n",
191 SanitizerToolName, class_id, ClassIdToSize(class_id));
191192 Die();
192193 }
193194 for (uptr i = 0; i < n_chunks; i++)
......@@ -763,8 +764,9 @@ class SizeClassAllocator64 {
763764 if (!region->exhausted) {
764765 region->exhausted = true;
765766 Printf("%s: Out of memory. ", SanitizerToolName);
766 Printf("The process has exhausted %zuMB for size class %zu.\n",
767 kRegionSize >> 20, ClassIdToSize(class_id));
767 Printf(
768 "The process has exhausted %zu MB for size class %zu (%zu bytes).\n",
769 kRegionSize >> 20, class_id, ClassIdToSize(class_id));
768770 }
769771 return true;
770772 }
lib/tsan/sanitizer_common/sanitizer_common.h+18-9
......@@ -83,8 +83,8 @@ int TgKill(pid_t pid, tid_t tid, int sig);
8383uptr GetThreadSelf();
8484void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
8585 uptr *stack_bottom);
86void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
87 uptr *tls_addr, uptr *tls_size);
86void GetThreadStackAndTls(bool main, uptr *stk_begin, uptr *stk_end,
87 uptr *tls_begin, uptr *tls_end);
8888
8989// Memory management
9090void *MmapOrDie(uptr size, const char *mem_type, bool raw_report = false);
......@@ -239,13 +239,15 @@ void RemoveANSIEscapeSequencesFromString(char *buffer);
239239void Printf(const char *format, ...) FORMAT(1, 2);
240240void Report(const char *format, ...) FORMAT(1, 2);
241241void SetPrintfAndReportCallback(void (*callback)(const char *));
242#define VReport(level, ...) \
243 do { \
244 if ((uptr)Verbosity() >= (level)) Report(__VA_ARGS__); \
242#define VReport(level, ...) \
243 do { \
244 if (UNLIKELY((uptr)Verbosity() >= (level))) \
245 Report(__VA_ARGS__); \
245246 } while (0)
246#define VPrintf(level, ...) \
247 do { \
248 if ((uptr)Verbosity() >= (level)) Printf(__VA_ARGS__); \
247#define VPrintf(level, ...) \
248 do { \
249 if (UNLIKELY((uptr)Verbosity() >= (level))) \
250 Printf(__VA_ARGS__); \
249251 } while (0)
250252
251253// Lock sanitizer error reporting and protects against nested errors.
......@@ -266,7 +268,15 @@ class ScopedErrorReportLock {
266268extern uptr stoptheworld_tracer_pid;
267269extern uptr stoptheworld_tracer_ppid;
268270
271// Returns true if the entire range can be read.
269272bool 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
271281// Error report formatting.
272282const char *StripPathPrefix(const char *filepath,
......@@ -917,7 +927,6 @@ typedef void (*RangeIteratorCallback)(uptr begin, uptr end, void *arg);
917927
918928enum AndroidApiLevel {
919929 ANDROID_NOT_ANDROID = 0,
920 ANDROID_KITKAT = 19,
921930 ANDROID_LOLLIPOP_MR1 = 22,
922931 ANDROID_POST_LOLLIPOP = 23
923932};
lib/tsan/sanitizer_common/sanitizer_common_interceptors.inc+189-221
......@@ -41,6 +41,7 @@
4141#include "sanitizer_errno.h"
4242#include "sanitizer_placement_new.h"
4343#include "sanitizer_platform_interceptors.h"
44#include "sanitizer_platform_limits_posix.h"
4445#include "sanitizer_symbolizer.h"
4546#include "sanitizer_tls_get_addr.h"
4647
......@@ -127,6 +128,39 @@ extern const short *_toupper_tab_;
127128extern const short *_tolower_tab_;
128129#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
130164#if SANITIZER_MUSL && \
131165 (defined(__i386__) || defined(__arm__) || SANITIZER_MIPS32 || SANITIZER_PPC32)
132166// musl 1.2.0 on existing 32-bit architectures uses new symbol names for the
......@@ -313,7 +347,7 @@ extern const short *_tolower_tab_;
313347 uptr copy_length = internal_strnlen(s, size); \
314348 char *new_mem = (char *)WRAP(malloc)(copy_length + 1); \
315349 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)); \
317351 } \
318352 if (new_mem) { \
319353 COMMON_INTERCEPTOR_COPY_STRING(ctx, new_mem, s, copy_length); \
......@@ -411,7 +445,7 @@ INTERCEPTOR(SIZE_T, strnlen, const char *s, SIZE_T maxlen) {
411445#endif
412446
413447#if SANITIZER_INTERCEPT_STRNDUP
414INTERCEPTOR(char*, strndup, const char *s, uptr size) {
448INTERCEPTOR(char*, strndup, const char *s, usize size) {
415449 void *ctx;
416450 COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size);
417451}
......@@ -421,7 +455,7 @@ INTERCEPTOR(char*, strndup, const char *s, uptr size) {
421455#endif // SANITIZER_INTERCEPT_STRNDUP
422456
423457#if SANITIZER_INTERCEPT___STRNDUP
424INTERCEPTOR(char*, __strndup, const char *s, uptr size) {
458INTERCEPTOR(char*, __strndup, const char *s, usize size) {
425459 void *ctx;
426460 COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size);
427461}
......@@ -477,23 +511,23 @@ INTERCEPTOR(int, strcmp, const char *s1, const char *s2) {
477511}
478512
479513DECLARE_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,
481515 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) {
484518 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
485519 return internal_strncmp(s1, s2, size);
486520 void *ctx;
487521 COMMON_INTERCEPTOR_ENTER(ctx, strncmp, s1, s2, size);
488522 unsigned char c1 = 0, c2 = 0;
489 uptr i;
523 usize i;
490524 for (i = 0; i < size; i++) {
491525 c1 = (unsigned char)s1[i];
492526 c2 = (unsigned char)s2[i];
493527 if (c1 != c2 || c1 == '\0') break;
494528 }
495 uptr i1 = i;
496 uptr i2 = i;
529 usize i1 = i;
530 usize i2 = i;
497531 if (common_flags()->strict_string_checks) {
498532 for (; i1 < size && s1[i1]; i1++) {}
499533 for (; i2 < size && s2[i2]; i2++) {}
......@@ -542,21 +576,21 @@ INTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) {
542576}
543577
544578DECLARE_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,
546580 int result)
547581
548582INTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, SIZE_T size) {
549583 void *ctx;
550584 COMMON_INTERCEPTOR_ENTER(ctx, strncasecmp, s1, s2, size);
551585 unsigned char c1 = 0, c2 = 0;
552 uptr i;
586 usize i;
553587 for (i = 0; i < size; i++) {
554588 c1 = (unsigned char)s1[i];
555589 c2 = (unsigned char)s2[i];
556590 if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
557591 }
558 uptr i1 = i;
559 uptr i2 = i;
592 usize i1 = i;
593 usize i2 = i;
560594 if (common_flags()->strict_string_checks) {
561595 for (; i1 < size && s1[i1]; i1++) {}
562596 for (; i2 < size && s2[i2]; i2++) {}
......@@ -799,13 +833,13 @@ INTERCEPTOR(char *, strpbrk, const char *s1, const char *s2) {
799833
800834#if SANITIZER_INTERCEPT_MEMCMP
801835DECLARE_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,
803837 int result)
804838
805839// Common code for `memcmp` and `bcmp`.
806840int MemcmpInterceptorCommon(void *ctx,
807 int (*real_fn)(const void *, const void *, uptr),
808 const void *a1, const void *a2, uptr size) {
841 int (*real_fn)(const void *, const void *, usize),
842 const void *a1, const void *a2, usize size) {
809843 if (common_flags()->intercept_memcmp) {
810844 if (common_flags()->strict_memcmp) {
811845 // Check the entire regions even if the first bytes of the buffers are
......@@ -817,7 +851,7 @@ int MemcmpInterceptorCommon(void *ctx,
817851 unsigned char c1 = 0, c2 = 0;
818852 const unsigned char *s1 = (const unsigned char*)a1;
819853 const unsigned char *s2 = (const unsigned char*)a2;
820 uptr i;
854 usize i;
821855 for (i = 0; i < size; i++) {
822856 c1 = s1[i];
823857 c2 = s2[i];
......@@ -837,7 +871,7 @@ int MemcmpInterceptorCommon(void *ctx,
837871 return result;
838872}
839873
840INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
874INTERCEPTOR(int, memcmp, const void *a1, const void *a2, usize size) {
841875 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
842876 return internal_memcmp(a1, a2, size);
843877 void *ctx;
......@@ -851,7 +885,7 @@ INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
851885#endif
852886
853887#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) {
855889 if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
856890 return internal_memcmp(a1, a2, size);
857891 void *ctx;
......@@ -1104,7 +1138,7 @@ INTERCEPTOR(SSIZE_T, write, int fd, void *ptr, SIZE_T count) {
11041138#endif
11051139
11061140#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) {
11081142 // libc file streams can call user-supplied functions, see fopencookie.
11091143 void *ctx;
11101144 COMMON_INTERCEPTOR_ENTER(ctx, fwrite, p, size, nmemb, file);
......@@ -1255,6 +1289,12 @@ INTERCEPTOR(int, prctl, int option, unsigned long arg2, unsigned long arg3,
12551289 static const int PR_SET_VMA = 0x53564d41;
12561290 static const int PR_SCHED_CORE = 62;
12571291 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
12581298 if (option == PR_SET_VMA && arg2 == 0UL) {
12591299 char *name = (char *)arg5;
12601300 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,
12701310 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strlen(name) + 1);
12711311 } else if (res != -1 && option == PR_SCHED_CORE &&
12721312 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
12741321 }
12751322 return res;
12761323}
......@@ -2242,6 +2289,61 @@ INTERCEPTOR(int, pthread_getcpuclockid, uptr thread,
22422289#define INIT_CLOCK_GETCPUCLOCKID
22432290#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
22452347#if SANITIZER_INTERCEPT_GETITIMER
22462348INTERCEPTOR(int, getitimer, int which, void *curr_value) {
22472349 void *ctx;
......@@ -2287,6 +2389,25 @@ INTERCEPTOR(int, setitimer, int which, const void *new_value, void *old_value) {
22872389#define INIT_GETITIMER
22882390#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
22902411#if SANITIZER_INTERCEPT_GLOB
22912412static void unpoison_glob_t(void *ctx, __sanitizer_glob_t *pglob) {
22922413 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pglob, sizeof(*pglob));
......@@ -3427,23 +3548,27 @@ INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) {
34273548 COMMON_INTERCEPTOR_ENTER(ctx, ptrace, request, pid, addr, data);
34283549 __sanitizer_iovec local_iovec;
34293550
3430 if (data) {
3551 void *data_arg = ptrace_data_arg(request, addr, data);
3552 if (data_arg) {
34313553 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);
34333555 } 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);
34353558 } 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);
34373561 } 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);
34393564 } 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 invalid
3443 // write access. In this case copy the invalid address for further
3444 // inspection.
3567 // Some kernel might zero the iovec::iov_base in case of invalid
3568 // write access. In this case copy the invalid address for further
3569 // inspection.
34453570 } else if (request == ptrace_setregset || request == ptrace_getregset) {
3446 __sanitizer_iovec *iovec = (__sanitizer_iovec*)data;
3571 __sanitizer_iovec *iovec = (__sanitizer_iovec *)data_arg;
34473572 COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec, sizeof(*iovec));
34483573 local_iovec = *iovec;
34493574 if (request == ptrace_setregset)
......@@ -3456,23 +3581,26 @@ INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) {
34563581 // https://github.com/google/sanitizers/issues/321.
34573582 uptr res = REAL(ptrace)(request, pid, addr, data);
34583583
3459 if (!res && data) {
3584 if (!res && data_arg) {
34603585 // Note that PEEK* requests assign different meaning to the return value.
34613586 // This function does not handle them (nor does it need to).
34623587 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);
34643589 } 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);
34663592 } 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);
34683595 } 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);
34703598 } 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);
34723600 } 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));
34743602 } else if (request == ptrace_getregset) {
3475 __sanitizer_iovec *iovec = (__sanitizer_iovec*)data;
3603 __sanitizer_iovec *iovec = (__sanitizer_iovec *)data_arg;
34763604 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iovec, sizeof(*iovec));
34773605 COMMON_INTERCEPTOR_WRITE_RANGE(ctx, local_iovec.iov_base,
34783606 local_iovec.iov_len);
......@@ -6425,12 +6553,12 @@ static void MlockIsUnsupported() {
64256553 SanitizerToolName);
64266554}
64276555
6428INTERCEPTOR(int, mlock, const void *addr, uptr len) {
6556INTERCEPTOR(int, mlock, const void *addr, usize len) {
64296557 MlockIsUnsupported();
64306558 return 0;
64316559}
64326560
6433INTERCEPTOR(int, munlock, const void *addr, uptr len) {
6561INTERCEPTOR(int, munlock, const void *addr, usize len) {
64346562 MlockIsUnsupported();
64356563 return 0;
64366564}
......@@ -8823,83 +8951,6 @@ INTERCEPTOR(char *, RMD160Data, u8 *data, SIZE_T len, char *buf) {
88238951#define INIT_RMD160
88248952#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
89038954#if SANITIZER_INTERCEPT_FSEEK
89048955INTERCEPTOR(int, fseek, __sanitizer_FILE *stream, long int offset, int whence) {
89058956 void *ctx;
......@@ -9030,107 +9081,6 @@ INTERCEPTOR(char *, MD2Data, const unsigned char *data, unsigned int len,
90309081#define INIT_MD2
90319082#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
91349084#if SANITIZER_INTERCEPT_VIS
91359085INTERCEPTOR(char *, vis, char *dst, int c, int flag, int nextc) {
91369086 void *ctx;
......@@ -9980,7 +9930,7 @@ INTERCEPTOR(SSIZE_T, getrandom, void *buf, SIZE_T buflen, unsigned int flags) {
99809930 void *ctx;
99819931 COMMON_INTERCEPTOR_ENTER(ctx, getrandom, buf, buflen, flags);
99829932 // 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;
99849934 SSIZE_T n;
99859935 if ((flags & grnd_nonblock))
99869936 n = REAL(getrandom)(buf, buflen, flags);
......@@ -10296,6 +10246,23 @@ INTERCEPTOR(SSIZE_T, pwritev2, int fd, __sanitizer_iovec *iov, int iovcnt,
1029610246#define INIT_PWRITEV2
1029710247#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
1029910266#include "sanitizer_common_interceptors_netbsd_compat.inc"
1030010267
1030110268namespace __sanitizer {
......@@ -10373,8 +10340,10 @@ static void InitializeCommonInterceptors() {
1037310340 INIT_SETPWENT;
1037410341 INIT_CLOCK_GETTIME;
1037510342 INIT_CLOCK_GETCPUCLOCKID;
10343 INIT_TIMER_CREATE;
1037610344 INIT_GETITIMER;
1037710345 INIT_TIME;
10346 INIT_TIMESPEC_GET;
1037810347 INIT_GLOB;
1037910348 INIT_GLOB64;
1038010349 INIT___B64_TO;
......@@ -10588,10 +10557,8 @@ static void InitializeCommonInterceptors() {
1058810557 INIT_SHA1;
1058910558 INIT_MD4;
1059010559 INIT_RMD160;
10591 INIT_MD5;
1059210560 INIT_FSEEK;
1059310561 INIT_MD2;
10594 INIT_SHA2;
1059510562 INIT_VIS;
1059610563 INIT_CDB;
1059710564 INIT_GETFSENT;
......@@ -10617,6 +10584,7 @@ static void InitializeCommonInterceptors() {
1061710584 INIT_CPUSET_GETAFFINITY;
1061810585 INIT_PREADV2;
1061910586 INIT_PWRITEV2;
10587 INIT_FREADLINK;
1062010588
1062110589 INIT___PRINTF_CHK;
1062210590}
lib/tsan/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc+17-17
......@@ -82,7 +82,7 @@
8282#endif
8383
8484#if SANITIZER_INTERCEPT_MEMSET
85INTERCEPTOR(void *, memset, void *dst, int v, uptr size) {
85INTERCEPTOR(void *, memset, void *dst, int v, usize size) {
8686 void *ctx;
8787 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size);
8888}
......@@ -93,7 +93,7 @@ INTERCEPTOR(void *, memset, void *dst, int v, uptr size) {
9393#endif
9494
9595#if SANITIZER_INTERCEPT_MEMMOVE
96INTERCEPTOR(void *, memmove, void *dst, const void *src, uptr size) {
96INTERCEPTOR(void *, memmove, void *dst, const void *src, usize size) {
9797 void *ctx;
9898 COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size);
9999}
......@@ -104,7 +104,7 @@ INTERCEPTOR(void *, memmove, void *dst, const void *src, uptr size) {
104104#endif
105105
106106#if SANITIZER_INTERCEPT_MEMCPY
107INTERCEPTOR(void *, memcpy, void *dst, const void *src, uptr size) {
107INTERCEPTOR(void *, memcpy, void *dst, const void *src, usize size) {
108108 // On OS X, calling internal_memcpy here will cause memory corruptions,
109109 // because memcpy and memmove are actually aliases of the same
110110 // implementation. We need to use internal_memmove here.
......@@ -133,63 +133,63 @@ INTERCEPTOR(void *, memcpy, void *dst, const void *src, uptr size) {
133133#endif
134134
135135#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) {
137137 void *ctx;
138138 COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
139139}
140140
141INTERCEPTOR(void *, __aeabi_memmove4, void *to, const void *from, uptr size) {
141INTERCEPTOR(void *, __aeabi_memmove4, void *to, const void *from, usize size) {
142142 void *ctx;
143143 COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
144144}
145145
146INTERCEPTOR(void *, __aeabi_memmove8, void *to, const void *from, uptr size) {
146INTERCEPTOR(void *, __aeabi_memmove8, void *to, const void *from, usize size) {
147147 void *ctx;
148148 COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
149149}
150150
151INTERCEPTOR(void *, __aeabi_memcpy, void *to, const void *from, uptr size) {
151INTERCEPTOR(void *, __aeabi_memcpy, void *to, const void *from, usize size) {
152152 void *ctx;
153153 COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
154154}
155155
156INTERCEPTOR(void *, __aeabi_memcpy4, void *to, const void *from, uptr size) {
156INTERCEPTOR(void *, __aeabi_memcpy4, void *to, const void *from, usize size) {
157157 void *ctx;
158158 COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
159159}
160160
161INTERCEPTOR(void *, __aeabi_memcpy8, void *to, const void *from, uptr size) {
161INTERCEPTOR(void *, __aeabi_memcpy8, void *to, const void *from, usize size) {
162162 void *ctx;
163163 COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
164164}
165165
166166// Note the argument order.
167INTERCEPTOR(void *, __aeabi_memset, void *block, uptr size, int c) {
167INTERCEPTOR(void *, __aeabi_memset, void *block, usize size, int c) {
168168 void *ctx;
169169 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
170170}
171171
172INTERCEPTOR(void *, __aeabi_memset4, void *block, uptr size, int c) {
172INTERCEPTOR(void *, __aeabi_memset4, void *block, usize size, int c) {
173173 void *ctx;
174174 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
175175}
176176
177INTERCEPTOR(void *, __aeabi_memset8, void *block, uptr size, int c) {
177INTERCEPTOR(void *, __aeabi_memset8, void *block, usize size, int c) {
178178 void *ctx;
179179 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
180180}
181181
182INTERCEPTOR(void *, __aeabi_memclr, void *block, uptr size) {
182INTERCEPTOR(void *, __aeabi_memclr, void *block, usize size) {
183183 void *ctx;
184184 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
185185}
186186
187INTERCEPTOR(void *, __aeabi_memclr4, void *block, uptr size) {
187INTERCEPTOR(void *, __aeabi_memclr4, void *block, usize size) {
188188 void *ctx;
189189 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
190190}
191191
192INTERCEPTOR(void *, __aeabi_memclr8, void *block, uptr size) {
192INTERCEPTOR(void *, __aeabi_memclr8, void *block, usize size) {
193193 void *ctx;
194194 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
195195}
......@@ -212,7 +212,7 @@ INTERCEPTOR(void *, __aeabi_memclr8, void *block, uptr size) {
212212#endif // SANITIZER_INTERCEPT_AEABI_MEM
213213
214214#if SANITIZER_INTERCEPT___BZERO
215INTERCEPTOR(void *, __bzero, void *block, uptr size) {
215INTERCEPTOR(void *, __bzero, void *block, usize size) {
216216 void *ctx;
217217 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
218218}
......@@ -222,7 +222,7 @@ INTERCEPTOR(void *, __bzero, void *block, uptr size) {
222222#endif // SANITIZER_INTERCEPT___BZERO
223223
224224#if SANITIZER_INTERCEPT_BZERO
225INTERCEPTOR(void *, bzero, void *block, uptr size) {
225INTERCEPTOR(void *, bzero, void *block, usize size) {
226226 void *ctx;
227227 COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
228228}
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 @@
1010INTERFACE_FUNCTION(__sanitizer_acquire_crash_state)
1111INTERFACE_FUNCTION(__sanitizer_annotate_contiguous_container)
1212INTERFACE_FUNCTION(__sanitizer_annotate_double_ended_contiguous_container)
13INTERFACE_FUNCTION(__sanitizer_copy_contiguous_container_annotations)
1314INTERFACE_FUNCTION(__sanitizer_contiguous_container_find_bad_address)
1415INTERFACE_FUNCTION(
1516 __sanitizer_double_ended_contiguous_container_find_bad_address)
......@@ -22,6 +23,7 @@ INTERFACE_FUNCTION(__sanitizer_verify_double_ended_contiguous_container)
2223INTERFACE_WEAK_FUNCTION(__sanitizer_on_print)
2324INTERFACE_WEAK_FUNCTION(__sanitizer_report_error_summary)
2425INTERFACE_WEAK_FUNCTION(__sanitizer_sandbox_on_notify)
26INTERFACE_WEAK_FUNCTION(__sanitizer_get_dtls_size)
2527// Sanitizer weak hooks
2628INTERFACE_WEAK_FUNCTION(__sanitizer_weak_hook_memcmp)
2729INTERFACE_WEAK_FUNCTION(__sanitizer_weak_hook_strcmp)
......@@ -51,3 +53,9 @@ INTERFACE_WEAK_FUNCTION(__sanitizer_ignore_free_hook)
5153INTERFACE_FUNCTION(__sanitizer_internal_memcpy)
5254INTERFACE_FUNCTION(__sanitizer_internal_memmove)
5355INTERFACE_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,
171171 "ReserveShadowMemoryRange failed while trying to map 0x%zx bytes. "
172172 "Perhaps you're using ulimit -v or ulimit -d\n",
173173 size);
174 Abort();
174 Die();
175175 }
176176 if (madvise_shadow && common_flags()->use_madv_dontdump)
177177 DontDumpShadowMemory(beg, size);
......@@ -219,6 +219,32 @@ static void StopStackDepotBackgroundThread() {
219219static void StopStackDepotBackgroundThread() {}
220220#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
222248} // namespace __sanitizer
223249
224250SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_sandbox_on_notify,
lib/tsan/sanitizer_common/sanitizer_common_nolibc.cpp+4-3
......@@ -20,13 +20,14 @@ namespace __sanitizer {
2020// The Windows implementations of these functions use the win32 API directly,
2121// bypassing libc.
2222#if !SANITIZER_WINDOWS
23#if SANITIZER_LINUX
23# if SANITIZER_LINUX
2424void LogMessageOnPrintf(const char *str) {}
25#endif
25void InitTlsSize() {}
26# endif
2627void WriteToSyslog(const char *buffer) {}
2728void Abort() { internal__exit(1); }
2829bool CreateDir(const char *pathname) { return false; }
29#endif // !SANITIZER_WINDOWS
30#endif // !SANITIZER_WINDOWS
3031
3132#if !SANITIZER_WINDOWS && !SANITIZER_APPLE
3233void ListOfModules::init() {}
lib/tsan/sanitizer_common/sanitizer_common_syscalls.inc+18-15
......@@ -48,6 +48,7 @@
4848#if SANITIZER_LINUX
4949
5050# include "sanitizer_libc.h"
51# include "sanitizer_platform_limits_posix.h"
5152
5253# define PRE_SYSCALL(name) \
5354 SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_syscall_pre_impl_##name
......@@ -2530,18 +2531,19 @@ PRE_SYSCALL(ptrace)(long request, long pid, long addr, long data) {
25302531# if !SANITIZER_ANDROID && \
25312532 (defined(__i386) || defined(__x86_64) || defined(__mips64) || \
25322533 defined(__powerpc64__) || defined(__aarch64__) || defined(__s390__) || \
2533 defined(__loongarch__) || SANITIZER_RISCV64)
2534 if (data) {
2534 defined(__loongarch__) || SANITIZER_RISCV64 || defined(__sparc__))
2535 long data_arg = ptrace_data_arg(request, addr, data);
2536 if (data_arg) {
25352537 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);
25372539 } 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);
25392541 } 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);
25412543 } else if (request == ptrace_setsiginfo) {
2542 PRE_READ((void *)data, siginfo_t_sz);
2544 PRE_READ((void *)data_arg, siginfo_t_sz);
25432545 } else if (request == ptrace_setregset) {
2544 __sanitizer_iovec *iov = (__sanitizer_iovec *)data;
2546 __sanitizer_iovec *iov = (__sanitizer_iovec *)data_arg;
25452547 PRE_READ(iov->iov_base, iov->iov_len);
25462548 }
25472549 }
......@@ -2552,25 +2554,26 @@ POST_SYSCALL(ptrace)(long res, long request, long pid, long addr, long data) {
25522554# if !SANITIZER_ANDROID && \
25532555 (defined(__i386) || defined(__x86_64) || defined(__mips64) || \
25542556 defined(__powerpc64__) || defined(__aarch64__) || defined(__s390__) || \
2555 defined(__loongarch__) || SANITIZER_RISCV64)
2556 if (res >= 0 && data) {
2557 defined(__loongarch__) || SANITIZER_RISCV64 || defined(__sparc__))
2558 long data_arg = ptrace_data_arg(request, addr, data);
2559 if (res >= 0 && data_arg) {
25572560 // Note that this is different from the interceptor in
25582561 // sanitizer_common_interceptors.inc.
25592562 // PEEK* requests return resulting values through data pointer.
25602563 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);
25622565 } 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);
25642567 } 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);
25662569 } else if (request == ptrace_getsiginfo) {
2567 POST_WRITE((void *)data, siginfo_t_sz);
2570 POST_WRITE((void *)data_arg, siginfo_t_sz);
25682571 } else if (request == ptrace_getregset) {
2569 __sanitizer_iovec *iov = (__sanitizer_iovec *)data;
2572 __sanitizer_iovec *iov = (__sanitizer_iovec *)data_arg;
25702573 POST_WRITE(iov->iov_base, iov->iov_len);
25712574 } else if (request == ptrace_peekdata || request == ptrace_peektext ||
25722575 request == ptrace_peekuser) {
2573 POST_WRITE((void *)data, sizeof(void *));
2576 POST_WRITE((void *)data_arg, sizeof(void *));
25742577 }
25752578 }
25762579# 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 {
120120 u32 lock;
121121 u32 stk;
122122 };
123 LockWithContext all_locks_with_contexts_[64];
123 LockWithContext all_locks_with_contexts_[128];
124124 uptr n_all_locks_;
125125};
126126
lib/tsan/sanitizer_common/sanitizer_dense_map.h+41-29
......@@ -69,24 +69,14 @@ class DenseMapBase {
6969 setNumTombstones(0);
7070 }
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
7275 /// Return 1 if the specified key is in the map, 0 otherwise.
73 size_type count(const KeyT &Key) const {
74 const BucketT *TheBucket;
75 return LookupBucketFor(Key, TheBucket) ? 1 : 0;
76 }
76 size_type count(const KeyT &Key) const { return contains(Key) ? 1 : 0; }
7777
78 value_type *find(const KeyT &Key) {
79 BucketT *TheBucket;
80 if (LookupBucketFor(Key, TheBucket))
81 return TheBucket;
82 return nullptr;
83 }
84 const value_type *find(const KeyT &Key) const {
85 const BucketT *TheBucket;
86 if (LookupBucketFor(Key, TheBucket))
87 return TheBucket;
88 return nullptr;
89 }
78 value_type *find(const KeyT &Key) { return doFind(Key); }
79 const value_type *find(const KeyT &Key) const { return doFind(Key); }
9080
9181 /// Alternate version of find() which allows a different, and possibly
9282 /// less expensive, key type.
......@@ -95,25 +85,18 @@ class DenseMapBase {
9585 /// type used.
9686 template <class LookupKeyT>
9787 value_type *find_as(const LookupKeyT &Key) {
98 BucketT *TheBucket;
99 if (LookupBucketFor(Key, TheBucket))
100 return TheBucket;
101 return nullptr;
88 return doFind(Key);
10289 }
10390 template <class LookupKeyT>
10491 const value_type *find_as(const LookupKeyT &Key) const {
105 const BucketT *TheBucket;
106 if (LookupBucketFor(Key, TheBucket))
107 return TheBucket;
108 return nullptr;
92 return doFind(Key);
10993 }
11094
11195 /// lookup - Return the entry for the specified key, or a default
11296 /// constructed value if no such entry exists.
11397 ValueT lookup(const KeyT &Key) const {
114 const BucketT *TheBucket;
115 if (LookupBucketFor(Key, TheBucket))
116 return TheBucket->getSecond();
98 if (const BucketT *Bucket = doFind(Key))
99 return Bucket->getSecond();
117100 return ValueT();
118101 }
119102
......@@ -184,8 +167,8 @@ class DenseMapBase {
184167 }
185168
186169 bool erase(const KeyT &Val) {
187 BucketT *TheBucket;
188 if (!LookupBucketFor(Val, TheBucket))
170 BucketT *TheBucket = doFind(Val);
171 if (!TheBucket)
189172 return false; // not in map.
190173
191174 TheBucket->getSecond().~ValueT();
......@@ -449,6 +432,35 @@ class DenseMapBase {
449432 return TheBucket;
450433 }
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
452464 /// LookupBucketFor - Lookup the appropriate bucket for Val, returning it in
453465 /// FoundBucket. If the bucket contains the key and a value, this returns
454466 /// 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 {
2323COMPILER_CHECK(errno_ENOMEM == ENOMEM);
2424COMPILER_CHECK(errno_EBUSY == EBUSY);
2525COMPILER_CHECK(errno_EINVAL == EINVAL);
26COMPILER_CHECK(errno_ERANGE == ERANGE);
2627
2728// EOWNERDEAD is not present in some older platforms.
2829#if defined(EOWNERDEAD)
lib/tsan/sanitizer_common/sanitizer_errno_codes.h+1
......@@ -24,6 +24,7 @@ namespace __sanitizer {
2424#define errno_ENOMEM 12
2525#define errno_EBUSY 16
2626#define errno_EINVAL 22
27#define errno_ERANGE 34
2728#define errno_ENAMETOOLONG 36
2829#define errno_ENOSYS 38
2930
lib/tsan/sanitizer_common/sanitizer_fuchsia.cpp+5-2
......@@ -94,7 +94,6 @@ void DisableCoreDumperIfNecessary() {}
9494void InstallDeadlySignalHandlers(SignalHandlerType handler) {}
9595void SetAlternateSignalStack() {}
9696void UnsetAlternateSignalStack() {}
97void InitTlsSize() {}
9897
9998bool SignalContext::IsStackOverflow() const { return false; }
10099void SignalContext::DumpAllRegisters(void *context) { UNIMPLEMENTED(); }
......@@ -445,6 +444,11 @@ bool IsAccessibleMemoryRange(uptr beg, uptr size) {
445444 return status == ZX_OK;
446445}
447446
447bool TryMemCpy(void *dest, const void *src, uptr n) {
448 // TODO: implement.
449 return false;
450}
451
448452// FIXME implement on this platform.
449453void GetMemoryProfile(fill_profile_f cb, uptr *stats) {}
450454
......@@ -519,7 +523,6 @@ uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len) {
519523uptr MainThreadStackBase, MainThreadStackSize;
520524
521525bool GetRandom(void *buffer, uptr length, bool blocking) {
522 CHECK_LE(length, ZX_CPRNG_DRAW_MAX_LEN);
523526 _zx_cprng_draw(buffer, length);
524527 return true;
525528}
lib/tsan/sanitizer_common/sanitizer_getauxval.h+11-12
......@@ -21,22 +21,21 @@
2121
2222#if SANITIZER_LINUX || SANITIZER_FUCHSIA
2323
24# if (__GLIBC_PREREQ(2, 16) || (SANITIZER_ANDROID && __ANDROID_API__ >= 21) || \
25 SANITIZER_FUCHSIA) && \
26 !SANITIZER_GO
27# define SANITIZER_USE_GETAUXVAL 1
28# else
29# define SANITIZER_USE_GETAUXVAL 0
30# endif
31
32# if SANITIZER_USE_GETAUXVAL
33# include <sys/auxv.h>
34# else
24# if (__GLIBC_PREREQ(2, 16) || SANITIZER_ANDROID || SANITIZER_FUCHSIA) && \
25 !SANITIZER_GO
26# define SANITIZER_USE_GETAUXVAL 1
27# else
28# define SANITIZER_USE_GETAUXVAL 0
29# endif
30
31# if SANITIZER_USE_GETAUXVAL
32# include <sys/auxv.h>
33# else
3534// The weak getauxval definition allows to check for the function at runtime.
3635// This is useful for Android, when compiled at a lower API level yet running
3736// on a more recent platform that offers the function.
3837extern "C" SANITIZER_WEAK_ATTRIBUTE unsigned long getauxval(unsigned long type);
39# endif
38# endif
4039
4140#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);
4949SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
5050__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
5257SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump();
5358SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_coverage(
5459 const __sanitizer::uptr *pcs, const __sanitizer::uptr len);
......@@ -71,6 +76,11 @@ void __sanitizer_annotate_double_ended_contiguous_container(
7176 const void *old_container_beg, const void *old_container_end,
7277 const void *new_container_beg, const void *new_container_end);
7378SANITIZER_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
7484int __sanitizer_verify_contiguous_container(const void *beg, const void *mid,
7585 const void *end);
7686SANITIZER_INTERFACE_ATTRIBUTE
lib/tsan/sanitizer_common/sanitizer_internal_defs.h+23-17
......@@ -138,19 +138,25 @@
138138// in a portable way by the language itself.
139139namespace __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)
142151// 64-bit Windows uses LLP64 data model.
143152typedef unsigned long long uptr;
144153typedef signed long long sptr;
145#else
146# if (SANITIZER_WORDSIZE == 64) || SANITIZER_APPLE || SANITIZER_WINDOWS
147typedef unsigned long uptr;
148typedef signed long sptr;
149# else
154#elif defined(_WIN32)
150155typedef unsigned int uptr;
151156typedef signed int sptr;
152# endif
153#endif // defined(_WIN64)
157#else
158# error Unsupported compiler, missing __UINTPTR_TYPE__
159#endif // defined(__UINTPTR_TYPE__)
154160#if defined(__x86_64__)
155161// Since x32 uses ILP32 data model in 64-bit hardware mode, we must use
156162// 64-bit pointer to unwind stack frame.
......@@ -194,16 +200,13 @@ typedef u64 OFF64_T;
194200#ifdef __SIZE_TYPE__
195201typedef __SIZE_TYPE__ usize;
196202#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
205203typedef uptr usize;
206# endif
204#endif
205
206#if defined(__s390__) && !defined(__s390x__)
207typedef long ssize;
208#else
209typedef sptr ssize;
207210#endif
208211
209212typedef u64 tid_t;
......@@ -466,6 +469,9 @@ using namespace __sanitizer;
466469namespace __msan {
467470using namespace __sanitizer;
468471}
472namespace __nsan {
473using namespace __sanitizer;
474}
469475namespace __hwasan {
470476using namespace __sanitizer;
471477}
lib/tsan/sanitizer_common/sanitizer_libignore.cpp+15-13
......@@ -32,7 +32,7 @@ void LibIgnore::AddIgnoredLibrary(const char *name_templ) {
3232 lib->templ = internal_strdup(name_templ);
3333 lib->name = nullptr;
3434 lib->real_name = nullptr;
35 lib->loaded = false;
35 lib->range_id = kInvalidCodeRangeId;
3636}
3737
3838void LibIgnore::OnLibraryLoaded(const char *name) {
......@@ -43,7 +43,7 @@ void LibIgnore::OnLibraryLoaded(const char *name) {
4343 buf[0]) {
4444 for (uptr i = 0; i < count_; i++) {
4545 Lib *lib = &libs_[i];
46 if (!lib->loaded && (!lib->real_name) &&
46 if (!lib->loaded() && (!lib->real_name) &&
4747 TemplateMatch(lib->templ, name))
4848 lib->real_name = internal_strdup(buf.data());
4949 }
......@@ -70,28 +70,31 @@ void LibIgnore::OnLibraryLoaded(const char *name) {
7070 Die();
7171 }
7272 loaded = true;
73 if (lib->loaded)
73 if (lib->loaded())
7474 continue;
7575 VReport(1,
7676 "Matched called_from_lib suppression '%s' against library"
7777 " '%s'\n",
7878 lib->templ, mod.full_name());
79 lib->loaded = true;
8079 lib->name = internal_strdup(mod.full_name());
8180 const uptr idx =
8281 atomic_load(&ignored_ranges_count_, memory_order_relaxed);
8382 CHECK_LT(idx, ARRAY_SIZE(ignored_code_ranges_));
84 ignored_code_ranges_[idx].begin = range.beg;
85 ignored_code_ranges_[idx].end = range.end;
83 ignored_code_ranges_[idx].OnLoad(range.beg, range.end);
84 // Record the index of the ignored range.
85 lib->range_id = idx;
8686 atomic_store(&ignored_ranges_count_, idx + 1, memory_order_release);
8787 break;
8888 }
8989 }
90 if (lib->loaded && !loaded) {
91 Report("%s: library '%s' that was matched against called_from_lib"
92 " suppression '%s' is unloaded\n",
93 SanitizerToolName, lib->name, lib->templ);
94 Die();
90 if (lib->loaded() && !loaded) {
91 VReport(1,
92 "%s: library '%s' that was matched against called_from_lib"
93 " suppression '%s' is unloaded\n",
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;
9598 }
9699 }
97100
......@@ -110,8 +113,7 @@ void LibIgnore::OnLibraryLoaded(const char *name) {
110113 const uptr idx =
111114 atomic_load(&instrumented_ranges_count_, memory_order_relaxed);
112115 CHECK_LT(idx, ARRAY_SIZE(instrumented_code_ranges_));
113 instrumented_code_ranges_[idx].begin = range.beg;
114 instrumented_code_ranges_[idx].end = range.end;
116 instrumented_code_ranges_[idx].OnLoad(range.beg, range.end);
115117 atomic_store(&instrumented_ranges_count_, idx + 1,
116118 memory_order_release);
117119 }
lib/tsan/sanitizer_common/sanitizer_libignore.h+23-12
......@@ -49,25 +49,36 @@ class LibIgnore {
4949 bool IsPcInstrumented(uptr pc) const;
5050
5151 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
5257 struct Lib {
5358 char *templ;
5459 char *name;
5560 char *real_name; // target of symlink
56 bool loaded;
61 uptr range_id;
62 bool loaded() const { return range_id != kInvalidCodeRangeId; };
5763 };
5864
5965 struct LibCodeRange {
60 uptr begin;
61 uptr end;
62 };
66 bool IsInRange(uptr pc) const {
67 return (pc >= begin && pc < atomic_load(&end, memory_order_acquire));
68 }
6369
64 inline bool IsInRange(uptr pc, const LibCodeRange &range) const {
65 return (pc >= range.begin && pc < range.end);
66 }
70 void OnLoad(uptr b, uptr e) {
71 begin = b;
72 atomic_store(&end, e, memory_order_release);
73 }
6774
68 static const uptr kMaxIgnoredRanges = 128;
69 static const uptr kMaxInstrumentedRanges = 1024;
70 static const uptr kMaxLibs = 1024;
75 void OnUnload() { atomic_store(&end, 0, memory_order_release); }
76
77 private:
78 uptr begin;
79 // A value of 0 means the associated module was unloaded.
80 atomic_uintptr_t end;
81 };
7182
7283 // Hot part:
7384 atomic_uintptr_t ignored_ranges_count_;
......@@ -90,7 +101,7 @@ class LibIgnore {
90101inline bool LibIgnore::IsIgnored(uptr pc, bool *pc_in_ignored_lib) const {
91102 const uptr n = atomic_load(&ignored_ranges_count_, memory_order_acquire);
92103 for (uptr i = 0; i < n; i++) {
93 if (IsInRange(pc, ignored_code_ranges_[i])) {
104 if (ignored_code_ranges_[i].IsInRange(pc)) {
94105 *pc_in_ignored_lib = true;
95106 return true;
96107 }
......@@ -104,7 +115,7 @@ inline bool LibIgnore::IsIgnored(uptr pc, bool *pc_in_ignored_lib) const {
104115inline bool LibIgnore::IsPcInstrumented(uptr pc) const {
105116 const uptr n = atomic_load(&instrumented_ranges_count_, memory_order_acquire);
106117 for (uptr i = 0; i < n; i++) {
107 if (IsInRange(pc, instrumented_code_ranges_[i]))
118 if (instrumented_code_ranges_[i].IsInRange(pc))
108119 return true;
109120 }
110121 return false;
lib/tsan/sanitizer_common/sanitizer_linux.cpp+325-71
......@@ -107,7 +107,9 @@ extern struct ps_strings *__ps_strings;
107107# endif // SANITIZER_NETBSD
108108
109109# if SANITIZER_SOLARIS
110# include <stddef.h>
110111# include <stdlib.h>
112# include <sys/frame.h>
111113# include <thread.h>
112114# define environ _environ
113115# endif
......@@ -132,9 +134,10 @@ const int FUTEX_WAKE_PRIVATE = FUTEX_WAKE | FUTEX_PRIVATE_FLAG;
132134// Are we using 32-bit or 64-bit Linux syscalls?
133135// x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32
134136// but it still needs to use 64-bit syscalls.
135# if SANITIZER_LINUX && (defined(__x86_64__) || defined(__powerpc64__) || \
136 SANITIZER_WORDSIZE == 64 || \
137 (defined(__mips__) && _MIPS_SIM == _ABIN32))
137# if SANITIZER_LINUX && \
138 (defined(__x86_64__) || defined(__powerpc64__) || \
139 SANITIZER_WORDSIZE == 64 || \
140 (defined(__mips__) && defined(_ABIN32) && _MIPS_SIM == _ABIN32))
138141# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1
139142# else
140143# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0
......@@ -152,6 +155,8 @@ const int FUTEX_WAKE_PRIVATE = FUTEX_WAKE | FUTEX_PRIVATE_FLAG;
152155
153156# if SANITIZER_FREEBSD
154157# 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);
155160# endif
156161
157162namespace __sanitizer {
......@@ -160,33 +165,56 @@ void SetSigProcMask(__sanitizer_sigset_t *set, __sanitizer_sigset_t *oldset) {
160165 CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, set, oldset));
161166}
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
163179// Block asynchronous signals
164180void BlockSignals(__sanitizer_sigset_t *oldset) {
165 __sanitizer_sigset_t set;
166 internal_sigfillset(&set);
167# if SANITIZER_LINUX && !SANITIZER_ANDROID
181 __sanitizer_sigset_t newset;
182 internal_sigfillset(&newset);
183
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
168191 // Glibc uses SIGSETXID signal during setuid call. If this signal is blocked
169192 // on any thread, setuid call hangs.
170193 // See test/sanitizer_common/TestCases/Linux/setuid.c.
171 internal_sigdelset(&set, 33);
172# endif
173# if SANITIZER_LINUX
194 KeepUnblocked(newset, currentset, 33);
195# endif // !SANITIZER_ANDROID
196
174197 // Seccomp-BPF-sandboxed processes rely on SIGSYS to handle trapped syscalls.
175198 // If this signal is blocked, such calls cannot be handled and the process may
176199 // hang.
177 internal_sigdelset(&set, 31);
200 KeepUnblocked(newset, currentset, 31);
178201
202# if !SANITIZER_ANDROID
179203 // Don't block synchronous signals
180 internal_sigdelset(&set, SIGSEGV);
181 internal_sigdelset(&set, SIGBUS);
182 internal_sigdelset(&set, SIGILL);
183 internal_sigdelset(&set, SIGTRAP);
184 internal_sigdelset(&set, SIGABRT);
185 internal_sigdelset(&set, SIGFPE);
186 internal_sigdelset(&set, SIGPIPE);
187# endif
204 // but also don't unblock signals that the user had deliberately blocked.
205 // FIXME: https://github.com/google/sanitizers/issues/1816
206 KeepUnblocked(newset, currentset, SIGSEGV);
207 KeepUnblocked(newset, currentset, SIGBUS);
208 KeepUnblocked(newset, currentset, SIGILL);
209 KeepUnblocked(newset, currentset, SIGTRAP);
210 KeepUnblocked(newset, currentset, SIGABRT);
211 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);
190218}
191219
192220ScopedBlockSignals::ScopedBlockSignals(__sanitizer_sigset_t *copy) {
......@@ -218,7 +246,9 @@ ScopedBlockSignals::~ScopedBlockSignals() { SetSigProcMask(&saved_, nullptr); }
218246# if !SANITIZER_S390
219247uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd,
220248 u64 offset) {
221# if SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS
249# if SANITIZER_FREEBSD
250 return (uptr)__sys_mmap(addr, length, prot, flags, fd, offset);
251# elif SANITIZER_LINUX_USES_64BIT_SYSCALLS
222252 return internal_syscall(SYSCALL(mmap), (uptr)addr, length, prot, flags, fd,
223253 offset);
224254# else
......@@ -250,6 +280,11 @@ int internal_madvise(uptr addr, uptr length, int advice) {
250280 return internal_syscall(SYSCALL(madvise), addr, length, advice);
251281}
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
253288uptr internal_close(fd_t fd) { return internal_syscall(SYSCALL(close), fd); }
254289
255290uptr internal_open(const char *filename, int flags) {
......@@ -395,8 +430,9 @@ uptr internal_stat(const char *path, void *buf) {
395430 AT_NO_AUTOMOUNT, STATX_BASIC_STATS, (uptr)&bufx);
396431 statx_to_stat(&bufx, (struct stat *)buf);
397432 return res;
398# elif (SANITIZER_WORDSIZE == 64 || SANITIZER_X32 || \
399 (defined(__mips__) && _MIPS_SIM == _ABIN32)) && \
433# elif ( \
434 SANITIZER_WORDSIZE == 64 || SANITIZER_X32 || \
435 (defined(__mips__) && defined(_ABIN32) && _MIPS_SIM == _ABIN32)) && \
400436 !SANITIZER_SPARC
401437 return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf,
402438 0);
......@@ -433,8 +469,9 @@ uptr internal_lstat(const char *path, void *buf) {
433469 STATX_BASIC_STATS, (uptr)&bufx);
434470 statx_to_stat(&bufx, (struct stat *)buf);
435471 return res;
436# elif (defined(_LP64) || SANITIZER_X32 || \
437 (defined(__mips__) && _MIPS_SIM == _ABIN32)) && \
472# elif ( \
473 defined(_LP64) || SANITIZER_X32 || \
474 (defined(__mips__) && defined(_ABIN32) && _MIPS_SIM == _ABIN32)) && \
438475 !SANITIZER_SPARC
439476 return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf,
440477 AT_SYMLINK_NOFOLLOW);
......@@ -721,6 +758,11 @@ static void GetArgsAndEnv(char ***argv, char ***envp) {
721758# if !SANITIZER_GO
722759 if (&__libc_stack_end) {
723760 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
724766 // Normally argc can be obtained from *stack_end, however, on ARM glibc's
725767 // _start clobbers it:
726768 // 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) {
10141056
10151057# if !SANITIZER_NETBSD
10161058// ThreadLister implementation.
1017ThreadLister::ThreadLister(pid_t pid) : pid_(pid), buffer_(4096) {
1018 char task_directory_path[80];
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 }
1059ThreadLister::ThreadLister(pid_t pid) : buffer_(4096) {
1060 task_path_.AppendF("/proc/%d/task", pid);
10251061}
10261062
10271063ThreadLister::Result ThreadLister::ListThreads(
10281064 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());
10301068 return Error;
1031 internal_lseek(descriptor_, 0, SEEK_SET);
1069 }
1070 auto cleanup = at_scope_exit([&] { internal_close(descriptor); });
10321071 threads->clear();
10331072
10341073 Result result = Ok;
10351074 for (bool first_read = true;; first_read = false) {
1036 // Resize to max capacity if it was downsized by IsAlive.
1037 buffer_.resize(buffer_.capacity());
10381075 CHECK_GE(buffer_.size(), 4096);
10391076 uptr read = internal_getdents(
1040 descriptor_, (struct linux_dirent *)buffer_.data(), buffer_.size());
1077 descriptor, (struct linux_dirent *)buffer_.data(), buffer_.size());
10411078 if (!read)
10421079 return result;
10431080 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());
10451082 return Error;
10461083 }
10471084
......@@ -1079,26 +1116,33 @@ ThreadLister::Result ThreadLister::ListThreads(
10791116 }
10801117}
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) {
10831133 // /proc/%d/task/%d/status uses same call to detect alive threads as
10841134 // 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);
10901135 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);
10921140 if (!field)
10931141 return false;
10941142 field += internal_strlen(kPrefix);
10951143 return (int)internal_atoll(field) != 0;
10961144}
10971145
1098ThreadLister::~ThreadLister() {
1099 if (!internal_iserror(descriptor_))
1100 internal_close(descriptor_);
1101}
11021146# endif
11031147
11041148# if SANITIZER_WORDSIZE == 32
......@@ -1808,11 +1852,6 @@ int internal_uname(struct utsname *buf) {
18081852# endif
18091853
18101854# 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
18161855static int dl_iterate_phdr_test_cb(struct dl_phdr_info *info, size_t size,
18171856 void *data) {
18181857 // 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,
18281867static atomic_uint32_t android_api_level;
18291868
18301869static AndroidApiLevel AndroidDetectApiLevelStatic() {
1831# if __ANDROID_API__ <= 19
1832 return ANDROID_KITKAT;
1833# elif __ANDROID_API__ <= 22
1870# if __ANDROID_API__ <= 22
18341871 return ANDROID_LOLLIPOP_MR1;
18351872# else
18361873 return ANDROID_POST_LOLLIPOP;
......@@ -1838,8 +1875,6 @@ static AndroidApiLevel AndroidDetectApiLevelStatic() {
18381875}
18391876
18401877static AndroidApiLevel AndroidDetectApiLevel() {
1841 if (!&dl_iterate_phdr)
1842 return ANDROID_KITKAT; // K or lower
18431878 bool base_name_seen = false;
18441879 dl_iterate_phdr(dl_iterate_phdr_test_cb, &base_name_seen);
18451880 if (base_name_seen)
......@@ -2014,6 +2049,18 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
20142049 return Unknown;
20152050 return esr & ESR_ELx_WNR ? Write : Read;
20162051# 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
20172064 u32 flags = ucontext->uc_mcontext.__flags;
20182065 if (flags & SC_ADDRERR_RD)
20192066 return SignalContext::Read;
......@@ -2154,8 +2201,26 @@ bool SignalContext::IsTrueFaultingAddress() const {
21542201UNUSED
21552202static const char *RegNumToRegName(int reg) {
21562203 switch (reg) {
2157# if SANITIZER_LINUX
2204# if SANITIZER_LINUX && SANITIZER_GLIBC || SANITIZER_NETBSD
21582205# 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
21592224 case REG_RAX:
21602225 return "rax";
21612226 case REG_RBX:
......@@ -2189,6 +2254,16 @@ static const char *RegNumToRegName(int reg) {
21892254 case REG_R15:
21902255 return "r15";
21912256# 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
21922267 case REG_EAX:
21932268 return "eax";
21942269 case REG_EBX:
......@@ -2205,32 +2280,170 @@ static const char *RegNumToRegName(int reg) {
22052280 return "ebp";
22062281 case REG_ESP:
22072282 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";
22082350# endif
2209# endif
2351# endif // SANITIZER_LINUX && SANITIZER_GLIBC
22102352 default:
22112353 return NULL;
22122354 }
22132355 return NULL;
22142356}
22152357
2216# if SANITIZER_LINUX
2358# 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
22172409UNUSED
22182410static void DumpSingleReg(ucontext_t *ctx, int RegNum) {
22192411 const char *RegName = RegNumToRegName(RegNum);
2412# if SANITIZER_LINUX && SANITIZER_GLIBC || SANITIZER_NETBSD
22202413# if defined(__x86_64__)
22212414 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 );
22232422# 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));
22252436# else
22262437 (void)RegName;
22272438# endif
2228}
2439# else
2440 (void)RegName;
22292441# endif
2442}
22302443
22312444void SignalContext::DumpAllRegisters(void *context) {
22322445 ucontext_t *ucontext = (ucontext_t *)context;
2233# if SANITIZER_LINUX
2446# if SANITIZER_LINUX && SANITIZER_GLIBC || SANITIZER_NETBSD
22342447# if defined(__x86_64__)
22352448 Report("Register values:\n");
22362449 DumpSingleReg(ucontext, REG_RAX);
......@@ -2269,6 +2482,35 @@ void SignalContext::DumpAllRegisters(void *context) {
22692482 DumpSingleReg(ucontext, REG_EBP);
22702483 DumpSingleReg(ucontext, REG_ESP);
22712484 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 }
22722514# else
22732515 (void)ucontext;
22742516# endif
......@@ -2310,6 +2552,8 @@ void SignalContext::DumpAllRegisters(void *context) {
23102552# else
23112553 (void)ucontext;
23122554# endif
2555# else
2556 (void)ucontext;
23132557# endif
23142558 // FIXME: Implement this for other OSes and architectures.
23152559}
......@@ -2404,7 +2648,19 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
24042648# if SANITIZER_SOLARIS
24052649 ucontext_t *ucontext = (ucontext_t *)context;
24062650 *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;
24082664# else
24092665 // Historical BSDism here.
24102666 struct sigcontext *scontext = (struct sigcontext *)context;
......@@ -2415,8 +2671,8 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
24152671 *pc = scontext->si_regs.pc;
24162672 *sp = scontext->si_regs.u_regs[14];
24172673# endif
2418# endif
24192674 *bp = (uptr)((uhwptr *)*sp)[14] + STACK_BIAS;
2675# endif
24202676# elif defined(__mips__)
24212677 ucontext_t *ucontext = (ucontext_t *)context;
24222678 *pc = ucontext->uc_mcontext.pc;
......@@ -2459,9 +2715,7 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
24592715
24602716void SignalContext::InitPcSpBp() { GetPcSpBp(context, &pc, &sp, &bp); }
24612717
2462void InitializePlatformEarly() {
2463 // Do nothing.
2464}
2718void InitializePlatformEarly() { InitTlsSize(); }
24652719
24662720void CheckASLR() {
24672721# 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);
9797class ThreadLister {
9898 public:
9999 explicit ThreadLister(pid_t pid);
100 ~ThreadLister();
101100 enum Result {
102101 Error,
103102 Incomplete,
104103 Ok,
105104 };
106105 Result ListThreads(InternalMmapVector<tid_t> *threads);
106 const char *LoadStatus(tid_t tid);
107107
108108 private:
109 bool IsAlive(int tid);
109 bool IsAlive(tid_t tid);
110110
111 pid_t pid_;
112 int descriptor_ = -1;
111 InternalScopedString task_path_;
112 InternalScopedString status_path_;
113113 InternalMmapVector<char> buffer_;
114114};
115115
lib/tsan/sanitizer_common/sanitizer_linux_libcdep.cpp+171-129
......@@ -40,6 +40,10 @@
4040# include <sys/resource.h>
4141# include <syslog.h>
4242
43# if SANITIZER_GLIBC
44# include <gnu/libc-version.h>
45# endif
46
4347# if !defined(ElfW)
4448# define ElfW(type) Elf_##type
4549# endif
......@@ -53,7 +57,7 @@
5357// that, it was never implemented. So just define it to zero.
5458# undef MAP_NORESERVE
5559# define MAP_NORESERVE 0
56extern const Elf_Auxinfo *__elf_aux_vector;
60extern const Elf_Auxinfo *__elf_aux_vector __attribute__((weak));
5761extern "C" int __sys_sigaction(int signum, const struct sigaction *act,
5862 struct sigaction *oldact);
5963# endif
......@@ -196,27 +200,6 @@ bool SetEnv(const char *name, const char *value) {
196200}
197201# 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
220203// True if we can use dlpi_tls_data. glibc before 2.25 may leave NULL (BZ
221204// #19826) so dlpi_tls_data cannot be used.
222205//
......@@ -226,112 +209,166 @@ __attribute__((unused)) static bool GetLibcVersion(int *major, int *minor,
226209__attribute__((unused)) static int g_use_dlpi_tls_data;
227210
228211# if SANITIZER_GLIBC && !SANITIZER_GO
229__attribute__((unused)) static size_t g_tls_size;
230void InitTlsSize() {
231 int major, minor, patch;
232 g_use_dlpi_tls_data =
233 GetLibcVersion(&major, &minor, &patch) && major == 2 && minor >= 25;
234
235# if defined(__aarch64__) || defined(__x86_64__) || \
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
212static void GetGLibcVersion(int *major, int *minor, int *patch) {
213 const char *p = gnu_get_libc_version();
214 *major = internal_simple_strtoll(p, &p, 10);
215 // Caller does not expect anything else.
216 CHECK_EQ(*major, 2);
217 *minor = (*p == '.') ? internal_simple_strtoll(p + 1, &p, 10) : 0;
218 *patch = (*p == '.') ? internal_simple_strtoll(p + 1, &p, 10) : 0;
241219}
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
254221static uptr ThreadDescriptorSizeFallback() {
255 uptr val = 0;
256# if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
222# if defined(__x86_64__) || defined(__i386__) || defined(__arm__) || \
223 SANITIZER_RISCV64
257224 int major;
258225 int minor;
259226 int patch;
260 if (GetLibcVersion(&major, &minor, &patch) && major == 2) {
261 /* sizeof(struct pthread) values from various glibc versions. */
262 if (SANITIZER_X32)
263 val = 1728; // Assume only one particular version for x32.
264 // For ARM sizeof(struct pthread) changed in Glibc 2.23.
265 else if (SANITIZER_ARM)
266 val = minor <= 22 ? 1120 : 1216;
267 else if (minor <= 3)
268 val = FIRST_32_SECOND_64(1104, 1696);
269 else if (minor == 4)
270 val = FIRST_32_SECOND_64(1120, 1728);
271 else if (minor == 5)
272 val = FIRST_32_SECOND_64(1136, 1728);
273 else if (minor <= 9)
274 val = FIRST_32_SECOND_64(1136, 1712);
275 else if (minor == 10)
276 val = FIRST_32_SECOND_64(1168, 1776);
277 else if (minor == 11 || (minor == 12 && patch == 1))
278 val = FIRST_32_SECOND_64(1168, 2288);
279 else if (minor <= 14)
280 val = FIRST_32_SECOND_64(1168, 2304);
281 else if (minor < 32) // Unknown version
282 val = FIRST_32_SECOND_64(1216, 2304);
283 else // minor == 32
284 val = FIRST_32_SECOND_64(1344, 2496);
285 }
286# elif defined(__s390__) || defined(__sparc__)
227 GetGLibcVersion(&major, &minor, &patch);
228# endif
229
230# if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
231 /* sizeof(struct pthread) values from various glibc versions. */
232 if (SANITIZER_X32)
233 return 1728; // Assume only one particular version for x32.
234 // For ARM sizeof(struct pthread) changed in Glibc 2.23.
235 if (SANITIZER_ARM)
236 return minor <= 22 ? 1120 : 1216;
237 if (minor <= 3)
238 return FIRST_32_SECOND_64(1104, 1696);
239 if (minor == 4)
240 return FIRST_32_SECOND_64(1120, 1728);
241 if (minor == 5)
242 return FIRST_32_SECOND_64(1136, 1728);
243 if (minor <= 9)
244 return FIRST_32_SECOND_64(1136, 1712);
245 if (minor == 10)
246 return FIRST_32_SECOND_64(1168, 1776);
247 if (minor == 11 || (minor == 12 && patch == 1))
248 return FIRST_32_SECOND_64(1168, 2288);
249 if (minor <= 14)
250 return FIRST_32_SECOND_64(1168, 2304);
251 if (minor < 32) // Unknown version
252 return FIRST_32_SECOND_64(1216, 2304);
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__)
287268 // The size of a prefix of TCB including pthread::{specific_1stblock,specific}
288269 // suffices. Just return offsetof(struct pthread, specific_used), which hasn't
289270 // changed since 2007-05. Technically this applies to i386/x86_64 as well but
290271 // we call _dl_get_tls_static_info and need the precise size of struct
291272 // pthread.
292273 return FIRST_32_SECOND_64(524, 1552);
293# elif defined(__mips__)
274# endif
275
276# if defined(__mips__)
294277 // TODO(sagarthakur): add more values as per different glibc versions.
295 val = FIRST_32_SECOND_64(1152, 1776);
296# elif SANITIZER_LOONGARCH64
297 val = 1856; // from glibc 2.36
298# elif SANITIZER_RISCV64
299 int major;
300 int minor;
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 }
278 return FIRST_32_SECOND_64(1152, 1776);
279# endif
280
281# if SANITIZER_LOONGARCH64
282 return 1856; // from glibc 2.36
283# endif
312284
313# elif defined(__aarch64__)
285# if defined(__aarch64__)
314286 // The sizeof (struct pthread) is the same from GLIBC 2.17 to 2.22.
315 val = 1776;
316# elif defined(__powerpc64__)
317 val = 1776; // from glibc.ppc64le 2.20-8.fc21
287 return 1776;
288# endif
289
290# if defined(__powerpc64__)
291 return 1776; // from glibc.ppc64le 2.20-8.fc21
318292# endif
319 return val;
320293}
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() {
323 uptr val = atomic_load_relaxed(&thread_descriptor_size);
324 if (val)
325 return val;
326 // _thread_db_sizeof_pthread is a GLIBC_PRIVATE symbol that is exported in
327 // glibc 2.34 and later.
328 if (unsigned *psizeof = static_cast<unsigned *>(
329 dlsym(RTLD_DEFAULT, "_thread_db_sizeof_pthread")))
330 val = *psizeof;
331 if (!val)
332 val = ThreadDescriptorSizeFallback();
333 atomic_store_relaxed(&thread_descriptor_size, val);
334 return val;
308# if defined(__mips__)
309 // TODO(sagarthakur): add more values as per different glibc versions.
310 return FIRST_32_SECOND_64(1152, 1776);
311# endif
312
313# if SANITIZER_LOONGARCH64
314 return 1856; // from glibc 2.36
315# endif
316
317# if defined(__aarch64__)
318 // The sizeof (struct pthread) is the same from GLIBC 2.17 to 2.22.
319 return 1776;
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();
335372}
336373
337374# if defined(__mips__) || defined(__powerpc64__) || SANITIZER_RISCV64 || \
......@@ -354,7 +391,13 @@ static uptr TlsPreTcbSize() {
354391 return kTlsPreTcbSize;
355392}
356393# 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
358401namespace {
359402struct TlsBlock {
360403 uptr begin, end, align;
......@@ -626,25 +669,32 @@ uptr GetTlsSize() {
626669}
627670# endif
628671
629void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
630 uptr *tls_addr, uptr *tls_size) {
672void GetThreadStackAndTls(bool main, uptr *stk_begin, uptr *stk_end,
673 uptr *tls_begin, uptr *tls_end) {
631674# if SANITIZER_GO
632675 // 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;
634680# 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
637687 uptr stack_top, stack_bottom;
638688 GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
639 *stk_addr = stack_bottom;
640 *stk_size = stack_top - stack_bottom;
689 *stk_begin = stack_bottom;
690 *stk_end = stack_top;
641691
642692 if (!main) {
643693 // If stack and tls intersect, make them non-intersecting.
644 if (*tls_addr > *stk_addr && *tls_addr < *stk_addr + *stk_size) {
645 if (*stk_addr + *stk_size < *tls_addr + *tls_size)
646 *tls_size = *stk_addr + *stk_size - *tls_addr;
647 *stk_size = *tls_addr - *stk_addr;
694 if (*tls_begin > *stk_begin && *tls_begin < *stk_end) {
695 if (*stk_end < *tls_end)
696 *tls_end = *stk_end;
697 *stk_end = *tls_begin;
648698 }
649699 }
650700# endif
......@@ -723,11 +773,6 @@ static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) {
723773 return 0;
724774}
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
731776static bool requiresProcmaps() {
732777# if SANITIZER_ANDROID && __ANDROID_API__ <= 22
733778 // 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,
890935void WriteOneLineToSyslog(const char *s) {
891936 if (&async_safe_write_log) {
892937 async_safe_write_log(SANITIZER_ANDROID_LOG_INFO, GetProcessName(), s);
893 } else if (AndroidGetApiLevel() > ANDROID_KITKAT) {
894 syslog(LOG_INFO, "%s", s);
895938 } else {
896 CHECK(&__android_log_write);
897 __android_log_write(SANITIZER_ANDROID_LOG_INFO, nullptr, s);
939 syslog(LOG_INFO, "%s", s);
898940 }
899941}
900942
lib/tsan/sanitizer_common/sanitizer_mac.cpp+36-28
......@@ -45,7 +45,7 @@ extern char **environ;
4545# define SANITIZER_OS_TRACE 0
4646# endif
4747
48// import new crash reporting api
48// Integrate with CrashReporter library if available
4949# if defined(__has_include) && __has_include(<CrashReporterClient.h>)
5050# define HAVE_CRASHREPORTERCLIENT_H 1
5151# include <CrashReporterClient.h>
......@@ -545,9 +545,6 @@ uptr GetTlsSize() {
545545 return 0;
546546}
547547
548void InitTlsSize() {
549}
550
551548uptr TlsBaseAddr() {
552549 uptr segbase = 0;
553550#if defined(__x86_64__)
......@@ -572,21 +569,18 @@ uptr TlsSize() {
572569#endif
573570}
574571
575void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
576 uptr *tls_addr, uptr *tls_size) {
577#if !SANITIZER_GO
578 uptr stack_top, stack_bottom;
579 GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
580 *stk_addr = stack_bottom;
581 *stk_size = stack_top - stack_bottom;
582 *tls_addr = TlsBaseAddr();
583 *tls_size = TlsSize();
584#else
585 *stk_addr = 0;
586 *stk_size = 0;
587 *tls_addr = 0;
588 *tls_size = 0;
589#endif
572void GetThreadStackAndTls(bool main, uptr *stk_begin, uptr *stk_end,
573 uptr *tls_begin, uptr *tls_end) {
574# if !SANITIZER_GO
575 GetThreadStackTopAndBottom(main, stk_end, stk_begin);
576 *tls_begin = TlsBaseAddr();
577 *tls_end = *tls_begin + TlsSize();
578# else
579 *stk_begin = 0;
580 *stk_end = 0;
581 *tls_begin = 0;
582 *tls_end = 0;
583# endif
590584}
591585
592586void ListOfModules::init() {
......@@ -788,7 +782,11 @@ void WriteOneLineToSyslog(const char *s) {
788782 if (GetMacosAlignedVersion() >= MacosVersion(10, 12)) {
789783 os_log_error(OS_LOG_DEFAULT, "%{public}s", s);
790784 } else {
785#pragma clang diagnostic push
786// as_log is deprecated.
787#pragma clang diagnostic ignored "-Wdeprecated-declarations"
791788 asl_log(nullptr, nullptr, ASL_LEVEL_ERR, "%s", s);
789#pragma clang diagnostic pop
792790 }
793791#endif
794792}
......@@ -798,8 +796,13 @@ static char crashreporter_info_buff[__sanitizer::kErrorMessageBufferSize] = {};
798796static Mutex crashreporter_info_mutex;
799797
800798extern "C" {
801// Integrate with crash reporter libraries.
799
802800#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
803806CRASH_REPORTER_CLIENT_HIDDEN
804807struct crashreporter_annotations_t gCRAnnotations
805808 __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION))) = {
......@@ -810,17 +813,17 @@ struct crashreporter_annotations_t gCRAnnotations
810813 0,
811814 0,
812815 0,
813#if CRASHREPORTER_ANNOTATIONS_VERSION > 4
816# if CRASHREPORTER_ANNOTATIONS_VERSION > 4
814817 0,
815#endif
818# endif
816819};
817
818#else
819// fall back to old crashreporter api
820# endif
821# else
822// Revert to previous crash reporter API if client header is not available
820823static const char *__crashreporter_info__ __attribute__((__used__)) =
821824 &crashreporter_info_buff[0];
822825asm(".desc ___crashreporter_info__, 0x10");
823#endif
826#endif // HAVE_CRASHREPORTERCLIENT_H
824827
825828} // extern "C"
826829
......@@ -843,6 +846,9 @@ void LogFullErrorReport(const char *buffer) {
843846#if !SANITIZER_GO
844847 // Log with os_trace. This will make it into the crash log.
845848#if SANITIZER_OS_TRACE
849#pragma clang diagnostic push
850// os_trace is deprecated.
851#pragma clang diagnostic ignored "-Wdeprecated-declarations"
846852 if (GetMacosAlignedVersion() >= MacosVersion(10, 10)) {
847853 // os_trace requires the message (format parameter) to be a string literal.
848854 if (internal_strncmp(SanitizerToolName, "AddressSanitizer",
......@@ -860,6 +866,7 @@ void LogFullErrorReport(const char *buffer) {
860866 if (common_flags()->log_to_syslog)
861867 os_trace("Consult syslog for more information.");
862868 }
869#pragma clang diagnostic pop
863870#endif
864871
865872 // Log to syslog.
......@@ -970,8 +977,9 @@ static const char kDyldInsertLibraries[] = "DYLD_INSERT_LIBRARIES";
970977LowLevelAllocator allocator_for_env;
971978
972979static bool ShouldCheckInterceptors() {
973 // Restrict "interceptors working?" check to ASan and TSan.
974 const char *sanitizer_names[] = {"AddressSanitizer", "ThreadSanitizer"};
980 // Restrict "interceptors working?" check
981 const char *sanitizer_names[] = {"AddressSanitizer", "ThreadSanitizer",
982 "RealtimeSanitizer"};
975983 size_t count = sizeof(sanitizer_names) / sizeof(sanitizer_names[0]);
976984 for (size_t i = 0; i < count; i++) {
977985 if (internal_strcmp(sanitizer_names[i], SanitizerToolName) == 0)
lib/tsan/sanitizer_common/sanitizer_platform_interceptors.h+45-7
......@@ -84,6 +84,25 @@
8484#define SI_NOT_MAC 1
8585#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
87106#if SANITIZER_IOS
88107#define SI_IOS 1
89108#else
......@@ -183,9 +202,16 @@
183202#define SANITIZER_INTERCEPT_FPUTS SI_POSIX
184203#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
186210#define SANITIZER_INTERCEPT_PREAD64 (SI_GLIBC || SI_SOLARIS32)
187211#define SANITIZER_INTERCEPT_PWRITE64 (SI_GLIBC || SI_SOLARIS32)
188212
213#define SANITIZER_INTERCEPT_LSEEK64 (SI_GLIBC || SI_SOLARIS32)
214
189215#define SANITIZER_INTERCEPT_READV SI_POSIX
190216#define SANITIZER_INTERCEPT_WRITEV SI_POSIX
191217
......@@ -232,8 +258,12 @@
232258 (SI_FREEBSD || SI_NETBSD || SI_LINUX || SI_SOLARIS)
233259#define SANITIZER_INTERCEPT_CLOCK_GETCPUCLOCKID \
234260 (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
235264#define SANITIZER_INTERCEPT_GETITIMER SI_POSIX
236265#define SANITIZER_INTERCEPT_TIME SI_POSIX
266#define SANITIZER_INTERCEPT_TIMESPEC_GET SI_LINUX
237267#define SANITIZER_INTERCEPT_GLOB (SI_GLIBC || SI_SOLARIS)
238268#define SANITIZER_INTERCEPT_GLOB64 SI_GLIBC
239269#define SANITIZER_INTERCEPT___B64_TO SI_LINUX_NOT_ANDROID
......@@ -274,8 +304,9 @@
274304#if SI_LINUX_NOT_ANDROID && \
275305 (defined(__i386) || defined(__x86_64) || defined(__mips64) || \
276306 defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \
277 defined(__s390__) || defined(__loongarch__) || SANITIZER_RISCV64)
278#define SANITIZER_INTERCEPT_PTRACE 1
307 defined(__s390__) || defined(__loongarch__) || SANITIZER_RISCV64 || \
308 defined(__sparc__))
309# define SANITIZER_INTERCEPT_PTRACE 1
279310#else
280311#define SANITIZER_INTERCEPT_PTRACE 0
281312#endif
......@@ -314,6 +345,8 @@
314345#define SANITIZER_INTERCEPT_GETGROUPS SI_POSIX
315346#define SANITIZER_INTERCEPT_POLL SI_POSIX
316347#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)
317350#define SANITIZER_INTERCEPT_WORDEXP \
318351 (SI_FREEBSD || SI_NETBSD || (SI_MAC && !SI_IOS) || SI_LINUX_NOT_ANDROID || \
319352 SI_SOLARIS)
......@@ -494,7 +527,8 @@
494527#define SANITIZER_INTERCEPT_PVALLOC (SI_GLIBC || SI_ANDROID)
495528#define SANITIZER_INTERCEPT_CFREE (SI_GLIBC && !SANITIZER_RISCV64)
496529#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)
498532#define SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE (!SI_MAC && !SI_NETBSD)
499533#define SANITIZER_INTERCEPT_MCHECK_MPROBE SI_LINUX_NOT_ANDROID
500534#define SANITIZER_INTERCEPT_WCSLEN 1
......@@ -559,10 +593,8 @@
559593#define SANITIZER_INTERCEPT_SHA1 SI_NETBSD
560594#define SANITIZER_INTERCEPT_MD4 SI_NETBSD
561595#define SANITIZER_INTERCEPT_RMD160 SI_NETBSD
562#define SANITIZER_INTERCEPT_MD5 (SI_NETBSD || SI_FREEBSD)
563#define SANITIZER_INTERCEPT_FSEEK (SI_NETBSD || SI_FREEBSD)
596#define SANITIZER_INTERCEPT_FSEEK SI_POSIX
564597#define SANITIZER_INTERCEPT_MD2 SI_NETBSD
565#define SANITIZER_INTERCEPT_SHA2 (SI_NETBSD || SI_FREEBSD)
566598#define SANITIZER_INTERCEPT_CDB SI_NETBSD
567599#define SANITIZER_INTERCEPT_VIS (SI_NETBSD || SI_FREEBSD)
568600#define SANITIZER_INTERCEPT_POPEN SI_POSIX
......@@ -601,7 +633,13 @@
601633// FIXME: also available from musl 1.2.5
602634#define SANITIZER_INTERCEPT_PREADV2 (SI_LINUX && __GLIBC_PREREQ(2, 26))
603635#define SANITIZER_INTERCEPT_PWRITEV2 (SI_LINUX && __GLIBC_PREREQ(2, 26))
604
636#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)
605643// This macro gives a way for downstream users to override the above
606644// interceptor macros irrespective of the platform they are on. They have
607645// 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);
547547unsigned timeval_sz = sizeof(timeval);
548548unsigned uid_t_sz = sizeof(uid_t);
549549unsigned gid_t_sz = sizeof(gid_t);
550unsigned fpos_t_sz = sizeof(fpos_t);
550551unsigned mbstate_t_sz = sizeof(mbstate_t);
551552unsigned sigset_t_sz = sizeof(sigset_t);
552553unsigned struct_timezone_sz = sizeof(struct timezone);
......@@ -2487,8 +2488,6 @@ const unsigned RMD160_return_length = RMD160_DIGEST_STRING_LENGTH;
24872488const unsigned MD5_CTX_sz = sizeof(MD5_CTX);
24882489const unsigned MD5_return_length = MD5_DIGEST_STRING_LENGTH;
24892490
2490const unsigned fpos_t_sz = sizeof(fpos_t);
2491
24922491const unsigned MD2_CTX_sz = sizeof(MD2_CTX);
24932492const 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;
3636extern unsigned timeval_sz;
3737extern unsigned uid_t_sz;
3838extern unsigned gid_t_sz;
39extern unsigned fpos_t_sz;
3940extern unsigned mbstate_t_sz;
4041extern unsigned struct_timezone_sz;
4142extern unsigned struct_tms_sz;
......@@ -2335,8 +2336,6 @@ extern const unsigned RMD160_return_length;
23352336extern const unsigned MD5_CTX_sz;
23362337extern const unsigned MD5_return_length;
23372338
2338extern const unsigned fpos_t_sz;
2339
23402339extern const unsigned MD2_CTX_sz;
23412340extern const unsigned MD2_return_length;
23422341
lib/tsan/sanitizer_common/sanitizer_platform_limits_posix.cpp+35-26
......@@ -94,8 +94,9 @@
9494#if SANITIZER_LINUX
9595# include <utime.h>
9696# include <sys/ptrace.h>
97# if defined(__mips64) || defined(__aarch64__) || defined(__arm__) || \
98 defined(__hexagon__) || defined(__loongarch__) ||SANITIZER_RISCV64
97# if defined(__mips64) || defined(__aarch64__) || defined(__arm__) || \
98 defined(__hexagon__) || defined(__loongarch__) || SANITIZER_RISCV64 || \
99 defined(__sparc__)
99100# include <asm/ptrace.h>
100101# ifdef __arm__
101102typedef struct user_fpregs elf_fpregset_t;
......@@ -117,15 +118,16 @@ typedef struct user_fpregs elf_fpregset_t;
117118#if SANITIZER_LINUX
118119#if SANITIZER_GLIBC
119120#include <fstab.h>
120#include <net/if_ppp.h>
121#include <netax25/ax25.h>
122#include <netipx/ipx.h>
123#include <netrom/netrom.h>
124#include <obstack.h>
125#if HAVE_RPC_XDR_H
126# include <rpc/xdr.h>
127#endif
128#include <scsi/scsi.h>
121# include <linux/filter.h>
122# include <net/if_ppp.h>
123# include <netax25/ax25.h>
124# include <netipx/ipx.h>
125# include <netrom/netrom.h>
126# include <obstack.h>
127# if HAVE_RPC_XDR_H
128# include <rpc/xdr.h>
129# endif
130# include <scsi/scsi.h>
129131#else
130132#include <linux/if_ppp.h>
131133#include <linux/kd.h>
......@@ -358,11 +360,12 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
358360 const int wordexp_wrde_dooffs = WRDE_DOOFFS;
359361# endif // !SANITIZER_ANDROID
360362
361#if SANITIZER_LINUX && !SANITIZER_ANDROID && \
362 (defined(__i386) || defined(__x86_64) || defined(__mips64) || \
363 defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \
364 defined(__s390__) || defined(__loongarch__)|| SANITIZER_RISCV64)
365#if defined(__mips64) || defined(__powerpc64__) || defined(__arm__)
363# if SANITIZER_LINUX && !SANITIZER_ANDROID && \
364 (defined(__i386) || defined(__x86_64) || defined(__mips64) || \
365 defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \
366 defined(__s390__) || defined(__loongarch__) || SANITIZER_RISCV64 || \
367 defined(__sparc__))
368# if defined(__mips64) || defined(__powerpc64__) || defined(__arm__)
366369 unsigned struct_user_regs_struct_sz = sizeof(struct pt_regs);
367370 unsigned struct_user_fpregs_struct_sz = sizeof(elf_fpregset_t);
368371#elif SANITIZER_RISCV64
......@@ -377,19 +380,22 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
377380#elif defined(__s390__)
378381 unsigned struct_user_regs_struct_sz = sizeof(struct _user_regs_struct);
379382 unsigned struct_user_fpregs_struct_sz = sizeof(struct _user_fpregs_struct);
380#else
383# 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
381387 unsigned struct_user_regs_struct_sz = sizeof(struct user_regs_struct);
382388 unsigned struct_user_fpregs_struct_sz = sizeof(struct user_fpregs_struct);
383#endif // __mips64 || __powerpc64__ || __aarch64__ || __loongarch__
384#if defined(__x86_64) || defined(__mips64) || defined(__powerpc64__) || \
385 defined(__aarch64__) || defined(__arm__) || defined(__s390__) || \
386 defined(__loongarch__) || SANITIZER_RISCV64
389# endif // __mips64 || __powerpc64__ || __aarch64__ || __loongarch__
390# if defined(__x86_64) || defined(__mips64) || defined(__powerpc64__) || \
391 defined(__aarch64__) || defined(__arm__) || defined(__s390__) || \
392 defined(__loongarch__) || SANITIZER_RISCV64 || defined(__sparc__)
387393 unsigned struct_user_fpxregs_struct_sz = 0;
388394#else
389395 unsigned struct_user_fpxregs_struct_sz = sizeof(struct user_fpxregs_struct);
390396#endif // __x86_64 || __mips64 || __powerpc64__ || __aarch64__ || __arm__
391// || __s390__ || __loongarch__
392#ifdef __arm__
397 // || __s390__ || __loongarch__ || SANITIZER_RISCV64 || __sparc__
398# ifdef __arm__
393399 unsigned struct_user_vfpregs_struct_sz = ARM_VFPREGS_SIZE;
394400#else
395401 unsigned struct_user_vfpregs_struct_sz = 0;
......@@ -531,13 +537,16 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
531537
532538 unsigned struct_audio_buf_info_sz = sizeof(struct audio_buf_info);
533539 unsigned struct_ppp_stats_sz = sizeof(struct ppp_stats);
534#endif // SANITIZER_GLIBC
540 unsigned struct_sock_fprog_sz = sizeof(struct sock_fprog);
541# endif // SANITIZER_GLIBC
535542
536#if !SANITIZER_ANDROID && !SANITIZER_APPLE
543# if !SANITIZER_ANDROID && !SANITIZER_APPLE
537544 unsigned struct_sioc_sg_req_sz = sizeof(struct sioc_sg_req);
538545 unsigned struct_sioc_vif_req_sz = sizeof(struct sioc_vif_req);
539546#endif
540547
548 unsigned fpos_t_sz = sizeof(fpos_t);
549
541550 const unsigned long __sanitizer_bufsiz = BUFSIZ;
542551
543552 const unsigned IOCTL_NOT_PRESENT = 0;
......@@ -1084,7 +1093,7 @@ CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_len);
10841093CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_level);
10851094CHECK_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))
10881097CHECK_TYPE_SIZE(mmsghdr);
10891098CHECK_SIZE_AND_OFFSET(mmsghdr, msg_hdr);
10901099CHECK_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;
9898const unsigned struct_kernel_stat_sz = 144;
9999const unsigned struct_kernel_stat64_sz = 104;
100100#elif defined(__mips__)
101const unsigned struct_kernel_stat_sz =
102 SANITIZER_ANDROID
103 ? FIRST_32_SECOND_64(104, 128)
104 : FIRST_32_SECOND_64((_MIPS_SIM == _ABIN32) ? 176 : 160, 216);
101const unsigned struct_kernel_stat_sz = SANITIZER_ANDROID
102 ? FIRST_32_SECOND_64(104, 128)
103# if defined(_ABIN32) && _MIPS_SIM == _ABIN32
104 : FIRST_32_SECOND_64(176, 216);
105# else
106 : FIRST_32_SECOND_64(160, 216);
107# endif
105108const unsigned struct_kernel_stat64_sz = 104;
106109#elif defined(__s390__) && !defined(__s390x__)
107110const unsigned struct_kernel_stat_sz = 64;
......@@ -313,7 +316,7 @@ extern unsigned struct_statvfs_sz;
313316
314317struct __sanitizer_iovec {
315318 void *iov_base;
316 uptr iov_len;
319 usize iov_len;
317320};
318321
319322#if !SANITIZER_ANDROID
......@@ -389,6 +392,16 @@ typedef long __sanitizer_time_t;
389392
390393typedef 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
392405struct __sanitizer_timeval {
393406 __sanitizer_time_t tv_sec;
394407 __sanitizer_suseconds_t tv_usec;
......@@ -513,6 +526,7 @@ struct __sanitizer_dirent64 {
513526 unsigned short d_reclen;
514527 // more fields that we don't care about
515528};
529extern unsigned struct_sock_fprog_sz;
516530#endif
517531
518532#if defined(__x86_64__) && !defined(_LP64)
......@@ -590,7 +604,7 @@ struct __sanitizer_siginfo_pad {
590604#if SANITIZER_LINUX
591605# define SANITIZER_HAS_SIGINFO 1
592606union __sanitizer_siginfo {
593 struct {
607 __extension__ struct {
594608 int si_signo;
595609# if SANITIZER_MIPS
596610 int si_code;
......@@ -855,10 +869,11 @@ typedef void __sanitizer_FILE;
855869# define SANITIZER_HAS_STRUCT_FILE 0
856870#endif
857871
858#if SANITIZER_LINUX && !SANITIZER_ANDROID && \
859 (defined(__i386) || defined(__x86_64) || defined(__mips64) || \
860 defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \
861 defined(__s390__) || defined(__loongarch__) || SANITIZER_RISCV64)
872# if SANITIZER_LINUX && !SANITIZER_ANDROID && \
873 (defined(__i386) || defined(__x86_64) || defined(__mips64) || \
874 defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \
875 defined(__s390__) || defined(__loongarch__) || SANITIZER_RISCV64 || \
876 defined(__sparc__))
862877extern unsigned struct_user_regs_struct_sz;
863878extern unsigned struct_user_fpregs_struct_sz;
864879extern unsigned struct_user_fpxregs_struct_sz;
......@@ -880,9 +895,24 @@ extern int ptrace_setsiginfo;
880895extern int ptrace_getregset;
881896extern int ptrace_setregset;
882897extern int ptrace_geteventmsg;
883#endif
884898
885#if SANITIZER_LINUX && !SANITIZER_ANDROID
899// 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
886916extern unsigned struct_shminfo_sz;
887917extern unsigned struct_shm_info_sz;
888918extern int shmctl_ipc_stat;
......@@ -1050,7 +1080,7 @@ extern unsigned struct_serial_struct_sz;
10501080extern unsigned struct_sockaddr_ax25_sz;
10511081extern unsigned struct_unimapdesc_sz;
10521082extern unsigned struct_unimapinit_sz;
1053#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
1083# endif // SANITIZER_LINUX && !SANITIZER_ANDROID
10541084
10551085extern const unsigned long __sanitizer_bufsiz;
10561086
......@@ -1064,6 +1094,8 @@ extern unsigned struct_sioc_sg_req_sz;
10641094extern unsigned struct_sioc_vif_req_sz;
10651095#endif
10661096
1097extern unsigned fpos_t_sz;
1098
10671099// ioctl request identifiers
10681100
10691101// A special value to mark ioctls that are not present on the target platform,
......@@ -1500,6 +1532,10 @@ extern const int si_SEGV_ACCERR;
15001532
15011533#define SIGACTION_SYMNAME sigaction
15021534
1535# if SANITIZER_LINUX
1536typedef void *__sanitizer_timer_t;
1537# endif
1538
15031539#endif // SANITIZER_LINUX || SANITIZER_APPLE
15041540
15051541#endif
lib/tsan/sanitizer_common/sanitizer_platform_limits_solaris.cpp+3
......@@ -32,6 +32,7 @@
3232#include <semaphore.h>
3333#include <signal.h>
3434#include <stddef.h>
35#include <stdio.h>
3536#include <sys/ethernet.h>
3637#include <sys/filio.h>
3738#include <sys/ipc.h>
......@@ -135,6 +136,8 @@ namespace __sanitizer {
135136 unsigned struct_sioc_sg_req_sz = sizeof(struct sioc_sg_req);
136137 unsigned struct_sioc_vif_req_sz = sizeof(struct sioc_vif_req);
137138
139 unsigned fpos_t_sz = sizeof(fpos_t);
140
138141 const unsigned IOCTL_NOT_PRESENT = 0;
139142
140143 unsigned IOCTL_FIOASYNC = FIOASYNC;
lib/tsan/sanitizer_common/sanitizer_platform_limits_solaris.h+2
......@@ -418,6 +418,8 @@ extern unsigned struct_winsize_sz;
418418extern unsigned struct_sioc_sg_req_sz;
419419extern unsigned struct_sioc_vif_req_sz;
420420
421extern unsigned fpos_t_sz;
422
421423// ioctl request identifiers
422424
423425// 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) {
353353 internal_strncmp(path, "/proc/", 6) == 0;
354354}
355355
356#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_GO
356bool 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
357365int GetNamedMappingFd(const char *name, uptr size, int *flags) {
358366 if (!common_flags()->decorate_proc_maps || !name)
359367 return -1;
lib/tsan/sanitizer_common/sanitizer_posix.h+5-1
......@@ -28,6 +28,9 @@ namespace __sanitizer {
2828// Don't use directly, use __sanitizer::OpenFile() instead.
2929uptr internal_open(const char *filename, int flags);
3030uptr 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
3134uptr internal_close(fd_t fd);
3235
3336uptr internal_read(fd_t fd, void *buf, uptr count);
......@@ -86,7 +89,7 @@ int internal_pthread_join(void *th, void **ret);
8689 return REAL(pthread_create)(th, attr, callback, param); \
8790 } \
8891 int internal_pthread_join(void *th, void **ret) { \
89 return REAL(pthread_join(th, ret)); \
92 return REAL(pthread_join)(th, ret); \
9093 } \
9194 } // namespace __sanitizer
9295
......@@ -108,6 +111,7 @@ bool IsStateDetached(int state);
108111fd_t ReserveStandardFds(fd_t fd);
109112
110113bool ShouldMockFailureToOpen(const char *path);
114bool OpenReadsVaArgs(int oflag);
111115
112116// Create a non-file mapping with a given /proc/self/maps name.
113117uptr 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 {
288288
289289#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
291300bool IsAccessibleMemoryRange(uptr beg, uptr size) {
292 uptr page_size = GetPageSizeCached();
293 // Checking too large memory ranges is slow.
294 CHECK_LT(size, page_size * 10);
295 int sock_pair[2];
296 if (pipe(sock_pair))
297 return false;
298 uptr bytes_written =
299 internal_write(sock_pair[1], reinterpret_cast<void *>(beg), size);
300 int write_errno;
301 bool result;
302 if (internal_iserror(bytes_written, &write_errno)) {
303 CHECK_EQ(EFAULT, write_errno);
304 result = false;
305 } else {
306 result = (bytes_written == size);
301 while (size) {
302 // `read` from `fds[0]` into a dummy buffer to free up the pipe buffer for
303 // more `write` is slower than just recreating a pipe.
304 int fds[2];
305 CHECK_EQ(0, pipe(fds));
306
307 auto cleanup = at_scope_exit([&]() {
308 internal_close(fds[0]);
309 internal_close(fds[1]);
310 });
311
312 SetNonBlock(fds[1]);
313
314 int write_errno;
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 }
307368 }
308 internal_close(sock_pair[0]);
309 internal_close(sock_pair[1]);
310 return result;
369
370 return true;
311371}
312372
313373void PlatformPrepareForSandboxing(void *args) {
......@@ -483,7 +543,11 @@ pid_t StartSubprocess(const char *program, const char *const argv[],
483543 internal_close(stderr_fd);
484544 }
485545
546# if SANITIZER_FREEBSD
547 internal_close_range(3, ~static_cast<fd_t>(0), 0);
548# else
486549 for (int fd = sysconf(_SC_OPEN_MAX); fd > 2; fd--) internal_close(fd);
550# endif
487551
488552 internal_execve(program, const_cast<char **>(&argv[0]),
489553 const_cast<char *const *>(envp));
lib/tsan/sanitizer_common/sanitizer_procmaps_mac.cpp+3-1
......@@ -433,7 +433,9 @@ void MemoryMappingLayout::DumpListOfModules(
433433 MemoryMappedSegmentData data;
434434 segment.data_ = &data;
435435 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;
437439 LoadedModule *cur_module = nullptr;
438440 if (!modules->empty() &&
439441 0 == internal_strcmp(segment.filename, modules->back().full_name())) {
lib/tsan/sanitizer_common/sanitizer_procmaps_solaris.cpp+4
......@@ -11,6 +11,10 @@
1111
1212// Before Solaris 11.4, <procfs.h> doesn't work in a largefile environment.
1313#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
1418#include "sanitizer_platform.h"
1519#if SANITIZER_SOLARIS
1620# include <fcntl.h>
lib/tsan/sanitizer_common/sanitizer_redefine_builtins.h+5-3
......@@ -17,9 +17,11 @@
1717// The asm hack only works with GCC and Clang.
1818# if !defined(_WIN32)
1919
20asm("memcpy = __sanitizer_internal_memcpy");
21asm("memmove = __sanitizer_internal_memmove");
22asm("memset = __sanitizer_internal_memset");
20asm(R"(
21 .set memcpy, __sanitizer_internal_memcpy
22 .set memmove, __sanitizer_internal_memmove
23 .set memset, __sanitizer_internal_memset
24 )");
2325
2426# if defined(__cplusplus) && \
2527 !defined(SANITIZER_COMMON_REDEFINE_BUILTINS_IN_STD)
lib/tsan/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp+11-4
......@@ -137,10 +137,6 @@ class ThreadSuspender {
137137};
138138
139139bool 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;
144140 int pterrno;
145141 if (internal_iserror(internal_ptrace(PTRACE_ATTACH, tid, nullptr, nullptr),
146142 &pterrno)) {
......@@ -217,17 +213,28 @@ bool ThreadSuspender::SuspendAllThreads() {
217213 switch (thread_lister.ListThreads(&threads)) {
218214 case ThreadLister::Error:
219215 ResumeAllThreads();
216 VReport(1, "Failed to list threads\n");
220217 return false;
221218 case ThreadLister::Incomplete:
219 VReport(1, "Incomplete list\n");
222220 retry = true;
223221 break;
224222 case ThreadLister::Ok:
225223 break;
226224 }
227225 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;
228231 if (SuspendThread(tid))
229232 retry = true;
233 else
234 VReport(2, "%llu/status: %s\n", tid, thread_lister.LoadStatus(tid));
230235 }
236 if (retry)
237 VReport(1, "SuspendAllThreads retry: %d\n", i);
231238 }
232239 return suspended_threads_list_.ThreadCount();
233240}
lib/tsan/sanitizer_common/sanitizer_symbolizer.h+4-4
......@@ -185,17 +185,17 @@ class Symbolizer final {
185185 class ModuleNameOwner {
186186 public:
187187 explicit ModuleNameOwner(Mutex *synchronized_by)
188 : last_match_(nullptr), mu_(synchronized_by) {
188 : mu_(synchronized_by), last_match_(nullptr) {
189189 storage_.reserve(kInitialCapacity);
190190 }
191191 const char *GetOwnedCopy(const char *str);
192192
193193 private:
194194 static const uptr kInitialCapacity = 1000;
195 InternalMmapVector<const char*> storage_;
196 const char *last_match_;
197195
198196 Mutex *mu_;
197 const char *last_match_ SANITIZER_GUARDED_BY(mu_);
198 InternalMmapVector<const char *> storage_ SANITIZER_GUARDED_BY(*mu_);
199199 } module_names_;
200200
201201 /// Platform-specific function for creating a Symbolizer object.
......@@ -220,7 +220,7 @@ class Symbolizer final {
220220 // always synchronized.
221221 Mutex mu_;
222222
223 IntrusiveList<SymbolizerTool> tools_;
223 IntrusiveList<SymbolizerTool> tools_ SANITIZER_GUARDED_BY(mu_);
224224
225225 explicit Symbolizer(IntrusiveList<SymbolizerTool> tools);
226226
lib/tsan/sanitizer_common/sanitizer_symbolizer_mac.cpp+2-2
......@@ -30,7 +30,7 @@ namespace __sanitizer {
3030bool DlAddrSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) {
3131 Dl_info info;
3232 int result = dladdr((const void *)addr, &info);
33 if (!result) return false;
33 if (!result || !info.dli_sname) return false;
3434
3535 // Compute offset if possible. `dladdr()` doesn't always ensure that `addr >=
3636 // 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) {
5151bool DlAddrSymbolizer::SymbolizeData(uptr addr, DataInfo *datainfo) {
5252 Dl_info info;
5353 int result = dladdr((const void *)addr, &info);
54 if (!result) return false;
54 if (!result || !info.dli_sname) return false;
5555 const char *demangled = DemangleSwiftAndCXX(info.dli_sname);
5656 if (!demangled)
5757 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,
227227 SanitizerToolName, kDescription, (void *)sig.addr, (void *)sig.pc,
228228 (void *)sig.bp, (void *)sig.sp, tid);
229229 Printf("%s", d.Default());
230 InternalMmapVector<BufferedStackTrace> stack_buffer(1);
231 BufferedStackTrace *stack = stack_buffer.data();
232 stack->Reset();
233 unwind(sig, unwind_context, stack);
234 stack->Print();
235 ReportErrorSummary(kDescription, stack);
230 // Avoid SEGVs in the unwinder when bp couldn't be determined.
231 if (sig.bp) {
232 InternalMmapVector<BufferedStackTrace> stack_buffer(1);
233 BufferedStackTrace *stack = stack_buffer.data();
234 stack->Reset();
235 unwind(sig, unwind_context, stack);
236 stack->Print();
237 ReportErrorSummary(kDescription, stack);
238 }
236239}
237240
238241static void ReportDeadlySignalImpl(const SignalContext &sig, u32 tid,
lib/tsan/sanitizer_common/sanitizer_symbolizer_win.cpp+7-6
......@@ -65,12 +65,13 @@ void InitializeDbgHelpIfNeeded() {
6565 HMODULE dbghelp = LoadLibraryA("dbghelp.dll");
6666 CHECK(dbghelp && "failed to load dbghelp.dll");
6767
68#define DBGHELP_IMPORT(name) \
69 do { \
70 name = \
71 reinterpret_cast<decltype(::name) *>(GetProcAddress(dbghelp, #name)); \
72 CHECK(name != nullptr); \
73 } while (0)
68# define DBGHELP_IMPORT(name) \
69 do { \
70 name = reinterpret_cast<decltype(::name) *>( \
71 (void *)GetProcAddress(dbghelp, #name)); \
72 CHECK(name != nullptr); \
73 } while (0)
74
7475 DBGHELP_IMPORT(StackWalk64);
7576 DBGHELP_IMPORT(SymCleanup);
7677 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 @@
1818namespace __sanitizer {
1919
2020ThreadContextBase::ThreadContextBase(u32 tid)
21 : tid(tid), unique_id(0), reuse_count(), os_id(0), user_id(0),
22 status(ThreadStatusInvalid), detached(false),
23 thread_type(ThreadType::Regular), parent_tid(0), next(0) {
21 : tid(tid),
22 unique_id(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) {
2432 name[0] = '\0';
2533 atomic_store(&thread_destroyed, 0, memory_order_release);
2634}
......@@ -39,8 +47,7 @@ void ThreadContextBase::SetName(const char *new_name) {
3947}
4048
4149void ThreadContextBase::SetDead() {
42 CHECK(status == ThreadStatusRunning ||
43 status == ThreadStatusFinished);
50 CHECK(status == ThreadStatusRunning || status == ThreadStatusFinished);
4451 status = ThreadStatusDead;
4552 user_id = 0;
4653 OnDead();
......@@ -68,7 +75,8 @@ void ThreadContextBase::SetFinished() {
6875 // for a thread that never actually started. In that case the thread
6976 // should go to ThreadStatusFinished regardless of whether it was created
7077 // as detached.
71 if (!detached || status == ThreadStatusCreated) status = ThreadStatusFinished;
78 if (!detached || status == ThreadStatusCreated)
79 status = ThreadStatusFinished;
7280 OnFinished();
7381}
7482
......@@ -81,14 +89,17 @@ void ThreadContextBase::SetStarted(tid_t _os_id, ThreadType _thread_type,
8189}
8290
8391void 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) {
8594 status = ThreadStatusCreated;
8695 user_id = _user_id;
8796 unique_id = _unique_id;
8897 detached = _detached;
8998 // Parent tid makes no sense for the main thread.
90 if (tid != kMainTid)
99 if (tid != kMainTid) {
91100 parent_tid = _parent_tid;
101 stack_id = _stack_tid;
102 }
92103 OnCreated(arg);
93104}
94105
......@@ -124,8 +135,10 @@ void ThreadRegistry::GetNumberOfThreads(uptr *total, uptr *running,
124135 ThreadRegistryLock l(this);
125136 if (total)
126137 *total = threads_.size();
127 if (running) *running = running_threads_;
128 if (alive) *alive = alive_threads_;
138 if (running)
139 *running = running_threads_;
140 if (alive)
141 *alive = alive_threads_;
129142}
130143
131144uptr ThreadRegistry::GetMaxAliveThreads() {
......@@ -134,7 +147,7 @@ uptr ThreadRegistry::GetMaxAliveThreads() {
134147}
135148
136149u32 ThreadRegistry::CreateThread(uptr user_id, bool detached, u32 parent_tid,
137 void *arg) {
150 u32 stack_tid, void *arg) {
138151 ThreadRegistryLock l(this);
139152 u32 tid = kInvalidTid;
140153 ThreadContextBase *tctx = QuarantinePop();
......@@ -150,8 +163,10 @@ u32 ThreadRegistry::CreateThread(uptr user_id, bool detached, u32 parent_tid,
150163 Report("%s: Thread limit (%u threads) exceeded. Dying.\n",
151164 SanitizerToolName, max_threads_);
152165#else
153 Printf("race: limit on %u simultaneously alive goroutines is exceeded,"
154 " dying\n", max_threads_);
166 Printf(
167 "race: limit on %u simultaneously alive goroutines is exceeded,"
168 " dying\n",
169 max_threads_);
155170#endif
156171 Die();
157172 }
......@@ -170,8 +185,8 @@ u32 ThreadRegistry::CreateThread(uptr user_id, bool detached, u32 parent_tid,
170185 // positives later (e.g. if we join a wrong thread).
171186 CHECK(live_.try_emplace(user_id, tid).second);
172187 }
173 tctx->SetCreated(user_id, total_threads_++, detached,
174 parent_tid, arg);
188 tctx->SetCreated(user_id, total_threads_++, detached, parent_tid, stack_tid,
189 arg);
175190 return tid;
176191}
177192
......@@ -196,8 +211,8 @@ u32 ThreadRegistry::FindThread(FindThreadCallback cb, void *arg) {
196211 return kInvalidTid;
197212}
198213
199ThreadContextBase *
200ThreadRegistry::FindThreadContextLocked(FindThreadCallback cb, void *arg) {
214ThreadContextBase *ThreadRegistry::FindThreadContextLocked(
215 FindThreadCallback cb, void *arg) {
201216 CheckLocked();
202217 for (u32 tid = 0; tid < threads_.size(); tid++) {
203218 ThreadContextBase *tctx = threads_[tid];
......@@ -210,7 +225,7 @@ ThreadRegistry::FindThreadContextLocked(FindThreadCallback cb, void *arg) {
210225static bool FindThreadContextByOsIdCallback(ThreadContextBase *tctx,
211226 void *arg) {
212227 return (tctx->os_id == (uptr)arg && tctx->status != ThreadStatusInvalid &&
213 tctx->status != ThreadStatusDead);
228 tctx->status != ThreadStatusDead);
214229}
215230
216231ThreadContextBase *ThreadRegistry::FindThreadContextByOsIDLocked(tid_t os_id) {
lib/tsan/sanitizer_common/sanitizer_thread_registry.h+8-3
......@@ -52,6 +52,7 @@ class ThreadContextBase {
5252 ThreadType thread_type;
5353
5454 u32 parent_tid;
55 u32 stack_id;
5556 ThreadContextBase *next; // For storing thread contexts in a list.
5657
5758 atomic_uint32_t thread_destroyed; // To address race of Joined vs Finished
......@@ -63,7 +64,7 @@ class ThreadContextBase {
6364 void SetFinished();
6465 void SetStarted(tid_t _os_id, ThreadType _thread_type, void *arg);
6566 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);
6768 void Reset();
6869
6970 void SetDestroyed();
......@@ -101,12 +102,16 @@ class SANITIZER_MUTEX ThreadRegistry {
101102
102103 // Should be guarded by ThreadRegistryLock.
103104 ThreadContextBase *GetThreadLocked(u32 tid) {
104 return threads_.empty() ? nullptr : threads_[tid];
105 return tid < threads_.size() ? threads_[tid] : nullptr;
105106 }
106107
107108 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
111116 typedef void (*ThreadCallback)(ThreadContextBase *tctx, void *arg);
112117 // 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 @@
1414
1515#include "sanitizer_allocator_interface.h"
1616#include "sanitizer_atomic.h"
17#include "sanitizer_common/sanitizer_common.h"
18#include "sanitizer_common/sanitizer_internal_defs.h"
1719#include "sanitizer_flags.h"
1820#include "sanitizer_platform_interceptors.h"
1921
......@@ -66,7 +68,7 @@ static DTLS::DTVBlock *DTLS_NextBlock(atomic_uintptr_t *cur) {
6668}
6769
6870static 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);
7072 static constexpr uptr kPerBlock = ARRAY_SIZE(DTLS::DTVBlock::dtvs);
7173 DTLS::DTVBlock *cur = DTLS_NextBlock(&dtls.dtv_block);
7274 if (!cur)
......@@ -110,6 +112,21 @@ SANITIZER_WEAK_ATTRIBUTE
110112const void *__sanitizer_get_allocated_begin(const void *p);
111113}
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
113130DTLS::DTV *DTLS_on_tls_get_addr(void *arg_void, void *res,
114131 uptr static_tls_begin, uptr static_tls_end) {
115132 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,
117134 uptr dso_id = arg->dso_id;
118135 DTLS::DTV *dtv = DTLS_Find(dso_id);
119136 if (!dtv || dtv->beg)
120 return 0;
121 uptr tls_size = 0;
137 return nullptr;
138 CHECK_LE(static_tls_begin, static_tls_end);
122139 uptr tls_beg = reinterpret_cast<uptr>(res) - arg->offset - kDtvOffset;
123140 VReport(2,
124141 "__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,
126143 (void *)arg, arg->dso_id, arg->offset, res, (void *)tls_beg,
127144 (void *)&tls_beg,
128145 atomic_load(&number_of_live_dtls, memory_order_relaxed));
129 if (dtls.last_memalign_ptr == tls_beg) {
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) {
146 if (tls_beg >= static_tls_begin && tls_beg < static_tls_end) {
134147 // This is the static TLS block which was initialized / unpoisoned at thread
135148 // creation.
136149 VReport(2, "__tls_get_addr: static tls: %p\n", (void *)tls_beg);
137 tls_size = 0;
138 } else if (const void *start =
139 __sanitizer_get_allocated_begin((void *)tls_beg)) {
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;
150 dtv->beg = tls_beg;
151 dtv->size = 0;
152 return nullptr;
148153 }
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}'.
149170 dtv->beg = tls_beg;
150 dtv->size = tls_size;
151 return dtv;
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;
171 dtv->size = 0;
172 return nullptr;
159173}
160174
161175DTLS *DTLS_Get() { return &dtls; }
......@@ -166,7 +180,9 @@ bool DTLSInDestruction(DTLS *dtls) {
166180}
167181
168182#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}
170186DTLS::DTV *DTLS_on_tls_get_addr(void *arg, void *res,
171187 unsigned long, unsigned long) { return 0; }
172188DTLS *DTLS_Get() { return 0; }
lib/tsan/sanitizer_common/sanitizer_tls_get_addr.h-4
......@@ -55,10 +55,6 @@ struct DTLS {
5555 static_assert(sizeof(DTVBlock) <= 4096UL, "Unexpected block size");
5656
5757 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;
6258};
6359
6460template <typename Fn>
lib/tsan/sanitizer_common/sanitizer_win.cpp+81-20
......@@ -164,7 +164,24 @@ void UnmapOrDie(void *addr, uptr size, bool raw_report) {
164164static void *ReturnNullptrOnOOMOrDie(uptr size, const char *mem_type,
165165 const char *mmap_type) {
166166 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)
168185 return nullptr;
169186 ReportMmapFailureAndDie(size, mem_type, mmap_type, last_error);
170187}
......@@ -873,24 +890,18 @@ uptr GetTlsSize() {
873890 return 0;
874891}
875892
876void InitTlsSize() {
877}
878
879void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
880 uptr *tls_addr, uptr *tls_size) {
881#if SANITIZER_GO
882 *stk_addr = 0;
883 *stk_size = 0;
884 *tls_addr = 0;
885 *tls_size = 0;
886#else
887 uptr stack_top, stack_bottom;
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
893void GetThreadStackAndTls(bool main, uptr *stk_begin, uptr *stk_end,
894 uptr *tls_begin, uptr *tls_end) {
895# if SANITIZER_GO
896 *stk_begin = 0;
897 *stk_end = 0;
898 *tls_begin = 0;
899 *tls_end = 0;
900# else
901 GetThreadStackTopAndBottom(main, stk_end, stk_begin);
902 *tls_begin = 0;
903 *tls_end = 0;
904# endif
894905}
895906
896907void ReportFile::Write(const char *buffer, uptr length) {
......@@ -974,6 +985,11 @@ bool IsAccessibleMemoryRange(uptr beg, uptr size) {
974985 return true;
975986}
976987
988bool TryMemCpy(void *dest, const void *src, uptr n) {
989 // TODO: implement.
990 return false;
991}
992
977993bool SignalContext::IsStackOverflow() const {
978994 return (DWORD)GetType() == EXCEPTION_STACK_OVERFLOW;
979995}
......@@ -1039,7 +1055,52 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
10391055}
10401056
10411057void 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
10431104}
10441105
10451106int 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 @@
1414#include "sanitizer_common/sanitizer_platform.h"
1515#if SANITIZER_APPLE
1616
17#include "interception/interception.h"
18#include "tsan_interceptors.h"
19#include "tsan_interface.h"
20#include "tsan_interface_ann.h"
21#include "tsan_spinlock_defs_mac.h"
22#include "sanitizer_common/sanitizer_addrhashmap.h"
23
24#include <errno.h>
25#include <libkern/OSAtomic.h>
26#include <objc/objc-sync.h>
27#include <os/lock.h>
28#include <sys/ucontext.h>
29
30#if defined(__has_include) && __has_include(<xpc/xpc.h>)
31#include <xpc/xpc.h>
32#endif // #if defined(__has_include) && __has_include(<xpc/xpc.h>)
17# include <errno.h>
18# include <libkern/OSAtomic.h>
19# include <objc/objc-sync.h>
20# include <os/lock.h>
21# include <sys/ucontext.h>
22
23# include "interception/interception.h"
24# include "sanitizer_common/sanitizer_addrhashmap.h"
25# include "tsan_interceptors.h"
26# include "tsan_interface.h"
27# include "tsan_interface_ann.h"
28
29# if defined(__has_include) && __has_include(<xpc/xpc.h>)
30# include <xpc/xpc.h>
31# endif // #if defined(__has_include) && __has_include(<xpc/xpc.h>)
3332
3433typedef long long_t;
3534
......@@ -49,51 +48,55 @@ static constexpr morder kMacOrderBarrier = mo_acq_rel;
4948static constexpr morder kMacOrderNonBarrier = mo_acq_rel;
5049static constexpr morder kMacFailureOrder = mo_relaxed;
5150
52#define OSATOMIC_INTERCEPTOR(return_t, t, tsan_t, f, tsan_atomic_f, mo) \
53 TSAN_INTERCEPTOR(return_t, f, t x, volatile t *ptr) { \
54 SCOPED_TSAN_INTERCEPTOR(f, x, ptr); \
55 return tsan_atomic_f((volatile tsan_t *)ptr, x, mo); \
56 }
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 }
51# define OSATOMIC_INTERCEPTOR(return_t, t, tsan_t, f, tsan_atomic_f, mo) \
52 TSAN_INTERCEPTOR(return_t, f, t x, volatile t *ptr) { \
53 SCOPED_TSAN_INTERCEPTOR(f, x, ptr); \
54 return tsan_atomic_f((volatile tsan_t *)ptr, x, mo); \
55 }
6356
64#define OSATOMIC_INTERCEPTOR_PLUS_1(return_t, t, tsan_t, f, tsan_atomic_f, mo) \
65 TSAN_INTERCEPTOR(return_t, f, volatile t *ptr) { \
66 SCOPED_TSAN_INTERCEPTOR(f, ptr); \
67 return tsan_atomic_f((volatile tsan_t *)ptr, 1, mo) + 1; \
68 }
57# define OSATOMIC_INTERCEPTOR_PLUS_X(return_t, t, tsan_t, f, tsan_atomic_f, \
58 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 }
6963
70#define OSATOMIC_INTERCEPTOR_MINUS_1(return_t, t, tsan_t, f, tsan_atomic_f, \
71 mo) \
72 TSAN_INTERCEPTOR(return_t, f, volatile t *ptr) { \
73 SCOPED_TSAN_INTERCEPTOR(f, ptr); \
74 return tsan_atomic_f((volatile tsan_t *)ptr, 1, mo) - 1; \
75 }
64# define OSATOMIC_INTERCEPTOR_PLUS_1(return_t, t, tsan_t, f, tsan_atomic_f, \
65 mo) \
66 TSAN_INTERCEPTOR(return_t, f, volatile t *ptr) { \
67 SCOPED_TSAN_INTERCEPTOR(f, ptr); \
68 return tsan_atomic_f((volatile tsan_t *)ptr, 1, mo) + 1; \
69 }
7670
77#define OSATOMIC_INTERCEPTORS_ARITHMETIC(f, tsan_atomic_f, m) \
78 m(int32_t, int32_t, a32, f##32, __tsan_atomic32_##tsan_atomic_f, \
79 kMacOrderNonBarrier) \
80 m(int32_t, int32_t, a32, f##32##Barrier, __tsan_atomic32_##tsan_atomic_f, \
81 kMacOrderBarrier) \
82 m(int64_t, int64_t, a64, f##64, __tsan_atomic64_##tsan_atomic_f, \
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)
71# define OSATOMIC_INTERCEPTOR_MINUS_1(return_t, t, tsan_t, f, tsan_atomic_f, \
72 mo) \
73 TSAN_INTERCEPTOR(return_t, f, volatile t *ptr) { \
74 SCOPED_TSAN_INTERCEPTOR(f, ptr); \
75 return tsan_atomic_f((volatile tsan_t *)ptr, 1, mo) - 1; \
76 }
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"
97100OSATOMIC_INTERCEPTORS_ARITHMETIC(OSAtomicAdd, fetch_add,
98101 OSATOMIC_INTERCEPTOR_PLUS_X)
99102OSATOMIC_INTERCEPTORS_ARITHMETIC(OSAtomicIncrement, fetch_add,
......@@ -106,23 +109,26 @@ OSATOMIC_INTERCEPTORS_BITWISE(OSAtomicAnd, fetch_and,
106109 OSATOMIC_INTERCEPTOR_PLUS_X, OSATOMIC_INTERCEPTOR)
107110OSATOMIC_INTERCEPTORS_BITWISE(OSAtomicXor, fetch_xor,
108111 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) \
111 TSAN_INTERCEPTOR(bool, f, t old_value, t new_value, t volatile *ptr) { \
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
130# pragma clang diagnostic push // OSAtomicCompareAndSwap* deprecation
131# pragma clang diagnostic ignored "-Wdeprecated-declarations"
126132OSATOMIC_INTERCEPTORS_CAS(OSAtomicCompareAndSwapInt, __tsan_atomic32, a32, int)
127133OSATOMIC_INTERCEPTORS_CAS(OSAtomicCompareAndSwapLong, __tsan_atomic64, a64,
128134 long_t)
......@@ -132,24 +138,28 @@ OSATOMIC_INTERCEPTORS_CAS(OSAtomicCompareAndSwap32, __tsan_atomic32, a32,
132138 int32_t)
133139OSATOMIC_INTERCEPTORS_CAS(OSAtomicCompareAndSwap64, __tsan_atomic64, a64,
134140 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) \
137 TSAN_INTERCEPTOR(bool, f, uint32_t n, volatile void *ptr) { \
138 SCOPED_TSAN_INTERCEPTOR(f, n, ptr); \
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)
153# define OSATOMIC_INTERCEPTORS_BITOP(f, op, clear) \
154 OSATOMIC_INTERCEPTOR_BITOP(f, op, clear, kMacOrderNonBarrier) \
155 OSATOMIC_INTERCEPTOR_BITOP(f##Barrier, op, clear, kMacOrderBarrier)
149156
157# pragma clang diagnostic push // OSAtomicTestAnd* deprecation
158# pragma clang diagnostic ignored "-Wdeprecated-declarations"
150159OSATOMIC_INTERCEPTORS_BITOP(OSAtomicTestAndSet, __tsan_atomic8_fetch_or, false)
151160OSATOMIC_INTERCEPTORS_BITOP(OSAtomicTestAndClear, __tsan_atomic8_fetch_and,
152161 true)
162# pragma clang diagnostic pop // OSAtomicTestAnd* deprecation
153163
154164TSAN_INTERCEPTOR(void, OSAtomicEnqueue, OSQueueHead *list, void *item,
155165 size_t offset) {
......@@ -161,12 +171,13 @@ TSAN_INTERCEPTOR(void, OSAtomicEnqueue, OSQueueHead *list, void *item,
161171TSAN_INTERCEPTOR(void *, OSAtomicDequeue, OSQueueHead *list, size_t offset) {
162172 SCOPED_TSAN_INTERCEPTOR(OSAtomicDequeue, list, offset);
163173 void *item = REAL(OSAtomicDequeue)(list, offset);
164 if (item) __tsan_acquire(item);
174 if (item)
175 __tsan_acquire(item);
165176 return item;
166177}
167178
168179// OSAtomicFifoEnqueue and OSAtomicFifoDequeue are only on OS X.
169#if !SANITIZER_IOS
180# if !SANITIZER_IOS
170181
171182TSAN_INTERCEPTOR(void, OSAtomicFifoEnqueue, OSFifoQueueHead *list, void *item,
172183 size_t offset) {
......@@ -179,11 +190,22 @@ TSAN_INTERCEPTOR(void *, OSAtomicFifoDequeue, OSFifoQueueHead *list,
179190 size_t offset) {
180191 SCOPED_TSAN_INTERCEPTOR(OSAtomicFifoDequeue, list, offset);
181192 void *item = REAL(OSAtomicFifoDequeue)(list, offset);
182 if (item) __tsan_acquire(item);
193 if (item)
194 __tsan_acquire(item);
183195 return item;
184196}
185197
186#endif
198# 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
188210TSAN_INTERCEPTOR(void, OSSpinLockLock, volatile OSSpinLock *lock) {
189211 CHECK(!cur_thread()->is_dead);
......@@ -216,6 +238,7 @@ TSAN_INTERCEPTOR(void, OSSpinLockUnlock, volatile OSSpinLock *lock) {
216238 Release(thr, pc, (uptr)lock);
217239 REAL(OSSpinLockUnlock)(lock);
218240}
241# pragma clang diagnostic pop // OSSpinLock* deprecation
219242
220243TSAN_INTERCEPTOR(void, os_lock_lock, void *lock) {
221244 CHECK(!cur_thread()->is_dead);
......@@ -288,7 +311,7 @@ TSAN_INTERCEPTOR(void, os_unfair_lock_unlock, os_unfair_lock_t lock) {
288311 REAL(os_unfair_lock_unlock)(lock);
289312}
290313
291#if defined(__has_include) && __has_include(<xpc/xpc.h>)
314# if defined(__has_include) && __has_include(<xpc/xpc.h>)
292315
293316TSAN_INTERCEPTOR(void, xpc_connection_set_event_handler,
294317 xpc_connection_t connection, xpc_handler_t handler) {
......@@ -342,7 +365,7 @@ TSAN_INTERCEPTOR(void, xpc_connection_cancel, xpc_connection_t connection) {
342365 REAL(xpc_connection_cancel)(connection);
343366}
344367
345#endif // #if defined(__has_include) && __has_include(<xpc/xpc.h>)
368# endif // #if defined(__has_include) && __has_include(<xpc/xpc.h>)
346369
347370// Determines whether the Obj-C object pointer is a tagged pointer. Tagged
348371// 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) {
365388 Map::Handle h(&Addresses, addr);
366389 if (h.created()) {
367390 ThreadIgnoreBegin(thr, pc);
368 *h = (uptr) user_alloc(thr, pc, /*size=*/1);
391 *h = (uptr)user_alloc(thr, pc, /*size=*/1);
369392 ThreadIgnoreEnd(thr);
370393 }
371394 return *h;
......@@ -383,7 +406,8 @@ static uptr SyncAddressForObjCObject(id obj, ThreadState *thr, uptr pc) {
383406
384407TSAN_INTERCEPTOR(int, objc_sync_enter, id obj) {
385408 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);
387411 uptr addr = SyncAddressForObjCObject(obj, thr, pc);
388412 MutexPreLock(thr, pc, addr, MutexFlagWriteReentrant);
389413 int result = REAL(objc_sync_enter)(obj);
......@@ -394,11 +418,13 @@ TSAN_INTERCEPTOR(int, objc_sync_enter, id obj) {
394418
395419TSAN_INTERCEPTOR(int, objc_sync_exit, id obj) {
396420 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);
398423 uptr addr = SyncAddressForObjCObject(obj, thr, pc);
399424 MutexUnlock(thr, pc, addr);
400425 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);
402428 return result;
403429}
404430
......@@ -429,7 +455,7 @@ TSAN_INTERCEPTOR(int, swapcontext, ucontext_t *oucp, const ucontext_t *ucp) {
429455
430456// On macOS, libc++ is always linked dynamically, so intercepting works the
431457// usual way.
432#define STDCXX_INTERCEPTOR TSAN_INTERCEPTOR
458# define STDCXX_INTERCEPTOR TSAN_INTERCEPTOR
433459
434460namespace {
435461struct fake_shared_weak_count {
lib/tsan/tsan_interceptors_posix.cpp+45-17
......@@ -12,14 +12,15 @@
1212// sanitizer_common/sanitizer_common_interceptors.inc
1313//===----------------------------------------------------------------------===//
1414
15#include "sanitizer_common/sanitizer_allocator_dlsym.h"
1516#include "sanitizer_common/sanitizer_atomic.h"
1617#include "sanitizer_common/sanitizer_errno.h"
1718#include "sanitizer_common/sanitizer_glibc_version.h"
19#include "sanitizer_common/sanitizer_internal_defs.h"
1820#include "sanitizer_common/sanitizer_libc.h"
1921#include "sanitizer_common/sanitizer_linux.h"
2022#include "sanitizer_common/sanitizer_platform_limits_netbsd.h"
2123#include "sanitizer_common/sanitizer_platform_limits_posix.h"
22#include "sanitizer_common/sanitizer_placement_new.h"
2324#include "sanitizer_common/sanitizer_posix.h"
2425#include "sanitizer_common/sanitizer_stacktrace.h"
2526#include "sanitizer_common/sanitizer_tls_get_addr.h"
......@@ -96,7 +97,7 @@ extern "C" int pthread_key_create(unsigned *key, void (*destructor)(void* v));
9697extern "C" int pthread_setspecific(unsigned key, const void *v);
9798DECLARE_REAL(int, pthread_mutexattr_gettype, void *, void *)
9899DECLARE_REAL(int, fflush, __sanitizer_FILE *fp)
99DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr size)
100DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, usize size)
100101DECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr)
101102extern "C" int pthread_equal(void *t1, void *t2);
102103extern "C" void *pthread_self();
......@@ -252,6 +253,13 @@ SANITIZER_WEAK_CXX_DEFAULT_IMPL void OnPotentiallyBlockingRegionBegin() {}
252253SANITIZER_WEAK_CXX_DEFAULT_IMPL void OnPotentiallyBlockingRegionEnd() {}
253254#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
255263} // namespace __tsan
256264
257265static ThreadSignalContext *SigCtx(ThreadState *thr) {
......@@ -661,6 +669,8 @@ TSAN_INTERCEPTOR(void, _longjmp, uptr *env, int val) {
661669TSAN_INTERCEPTOR(void*, malloc, uptr size) {
662670 if (in_symbolizer())
663671 return InternalAlloc(size);
672 if (DlsymAlloc::Use())
673 return DlsymAlloc::Allocate(size);
664674 void *p = 0;
665675 {
666676 SCOPED_INTERCEPTOR_RAW(malloc, size);
......@@ -678,12 +688,14 @@ TSAN_INTERCEPTOR(void*, __libc_memalign, uptr align, uptr sz) {
678688 return user_memalign(thr, pc, align, sz);
679689}
680690
681TSAN_INTERCEPTOR(void*, calloc, uptr size, uptr n) {
691TSAN_INTERCEPTOR(void *, calloc, uptr n, uptr size) {
682692 if (in_symbolizer())
683 return InternalCalloc(size, n);
693 return InternalCalloc(n, size);
694 if (DlsymAlloc::Use())
695 return DlsymAlloc::Callocate(n, size);
684696 void *p = 0;
685697 {
686 SCOPED_INTERCEPTOR_RAW(calloc, size, n);
698 SCOPED_INTERCEPTOR_RAW(calloc, n, size);
687699 p = user_calloc(thr, pc, size, n);
688700 }
689701 invoke_malloc_hook(p, n * size);
......@@ -693,6 +705,8 @@ TSAN_INTERCEPTOR(void*, calloc, uptr size, uptr n) {
693705TSAN_INTERCEPTOR(void*, realloc, void *p, uptr size) {
694706 if (in_symbolizer())
695707 return InternalRealloc(p, size);
708 if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(p))
709 return DlsymAlloc::Realloc(p, size);
696710 if (p)
697711 invoke_free_hook(p);
698712 {
......@@ -703,13 +717,13 @@ TSAN_INTERCEPTOR(void*, realloc, void *p, uptr size) {
703717 return p;
704718}
705719
706TSAN_INTERCEPTOR(void*, reallocarray, void *p, uptr size, uptr n) {
720TSAN_INTERCEPTOR(void *, reallocarray, void *p, uptr n, uptr size) {
707721 if (in_symbolizer())
708 return InternalReallocArray(p, size, n);
722 return InternalReallocArray(p, n, size);
709723 if (p)
710724 invoke_free_hook(p);
711725 {
712 SCOPED_INTERCEPTOR_RAW(reallocarray, p, size, n);
726 SCOPED_INTERCEPTOR_RAW(reallocarray, p, n, size);
713727 p = user_reallocarray(thr, pc, p, size, n);
714728 }
715729 invoke_malloc_hook(p, size);
......@@ -717,20 +731,24 @@ TSAN_INTERCEPTOR(void*, reallocarray, void *p, uptr size, uptr n) {
717731}
718732
719733TSAN_INTERCEPTOR(void, free, void *p) {
720 if (p == 0)
734 if (UNLIKELY(!p))
721735 return;
722736 if (in_symbolizer())
723737 return InternalFree(p);
738 if (DlsymAlloc::PointerIsMine(p))
739 return DlsymAlloc::Free(p);
724740 invoke_free_hook(p);
725741 SCOPED_INTERCEPTOR_RAW(free, p);
726742 user_free(thr, pc, p);
727743}
728744
729745TSAN_INTERCEPTOR(void, cfree, void *p) {
730 if (p == 0)
746 if (UNLIKELY(!p))
731747 return;
732748 if (in_symbolizer())
733749 return InternalFree(p);
750 if (DlsymAlloc::PointerIsMine(p))
751 return DlsymAlloc::Free(p);
734752 invoke_free_hook(p);
735753 SCOPED_INTERCEPTOR_RAW(cfree, p);
736754 user_free(thr, pc, p);
......@@ -750,7 +768,7 @@ TSAN_INTERCEPTOR(char *, strcpy, char *dst, const char *src) {
750768 return REAL(strcpy)(dst, src);
751769}
752770
753TSAN_INTERCEPTOR(char*, strncpy, char *dst, char *src, uptr n) {
771TSAN_INTERCEPTOR(char*, strncpy, char *dst, char *src, usize n) {
754772 SCOPED_TSAN_INTERCEPTOR(strncpy, dst, src, n);
755773 uptr srclen = internal_strnlen(src, n);
756774 MemoryAccessRange(thr, pc, (uptr)dst, n, true);
......@@ -1097,7 +1115,7 @@ int internal_pthread_create(void *th, void *attr, void *(*callback)(void *),
10971115}
10981116int internal_pthread_join(void *th, void **ret) {
10991117 ScopedIgnoreInterceptors ignore;
1100 return REAL(pthread_join(th, ret));
1118 return REAL(pthread_join)(th, ret);
11011119}
11021120} // namespace __sanitizer
11031121
......@@ -1662,13 +1680,23 @@ TSAN_INTERCEPTOR(int, fstat64, int fd, void *buf) {
16621680#endif
16631681
16641682TSAN_INTERCEPTOR(int, open, const char *name, int oflag, ...) {
1665 va_list ap;
1666 va_start(ap, oflag);
1667 mode_t mode = va_arg(ap, int);
1668 va_end(ap);
1683 mode_t mode = 0;
1684 if (OpenReadsVaArgs(oflag)) {
1685 va_list ap;
1686 va_start(ap, oflag);
1687 mode = va_arg(ap, int);
1688 va_end(ap);
1689 }
1690
16691691 SCOPED_TSAN_INTERCEPTOR(open, name, oflag, mode);
16701692 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
16721700 if (fd >= 0)
16731701 FdFileCreate(thr, pc, fd);
16741702 return fd;
lib/tsan/tsan_interface.h+76-75
......@@ -16,8 +16,8 @@
1616#define TSAN_INTERFACE_H
1717
1818#include <sanitizer_common/sanitizer_internal_defs.h>
19using __sanitizer::uptr;
2019using __sanitizer::tid_t;
20using __sanitizer::uptr;
2121
2222// This header should NOT include any other headers.
2323// 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,
203203namespace __tsan {
204204
205205// These should match declarations from public tsan_interface_atomic.h header.
206typedef unsigned char a8;
206typedef unsigned char a8;
207207typedef unsigned short a16;
208typedef unsigned int a32;
208typedef unsigned int a32;
209209typedef unsigned long long a64;
210#if !SANITIZER_GO && (defined(__SIZEOF_INT128__) \
211 || (__clang_major__ * 100 + __clang_minor__ >= 302)) && \
210#if !SANITIZER_GO && \
211 (defined(__SIZEOF_INT128__) || \
212 (__clang_major__ * 100 + __clang_minor__ >= 302)) && \
212213 !defined(__mips64) && !defined(__s390x__)
213214__extension__ typedef __int128 a128;
214# define __TSAN_HAS_INT128 1
215# define __TSAN_HAS_INT128 1
215216#else
216# define __TSAN_HAS_INT128 0
217# define __TSAN_HAS_INT128 0
217218#endif
218219
219220// Part of ABI, do not change.
......@@ -231,180 +232,180 @@ struct ThreadState;
231232
232233extern "C" {
233234SANITIZER_INTERFACE_ATTRIBUTE
234a8 __tsan_atomic8_load(const volatile a8 *a, morder mo);
235a8 __tsan_atomic8_load(const volatile a8 *a, int mo);
235236SANITIZER_INTERFACE_ATTRIBUTE
236a16 __tsan_atomic16_load(const volatile a16 *a, morder mo);
237a16 __tsan_atomic16_load(const volatile a16 *a, int mo);
237238SANITIZER_INTERFACE_ATTRIBUTE
238a32 __tsan_atomic32_load(const volatile a32 *a, morder mo);
239a32 __tsan_atomic32_load(const volatile a32 *a, int mo);
239240SANITIZER_INTERFACE_ATTRIBUTE
240a64 __tsan_atomic64_load(const volatile a64 *a, morder mo);
241a64 __tsan_atomic64_load(const volatile a64 *a, int mo);
241242#if __TSAN_HAS_INT128
242243SANITIZER_INTERFACE_ATTRIBUTE
243a128 __tsan_atomic128_load(const volatile a128 *a, morder mo);
244a128 __tsan_atomic128_load(const volatile a128 *a, int mo);
244245#endif
245246
246247SANITIZER_INTERFACE_ATTRIBUTE
247void __tsan_atomic8_store(volatile a8 *a, a8 v, morder mo);
248void __tsan_atomic8_store(volatile a8 *a, a8 v, int mo);
248249SANITIZER_INTERFACE_ATTRIBUTE
249void __tsan_atomic16_store(volatile a16 *a, a16 v, morder mo);
250void __tsan_atomic16_store(volatile a16 *a, a16 v, int mo);
250251SANITIZER_INTERFACE_ATTRIBUTE
251void __tsan_atomic32_store(volatile a32 *a, a32 v, morder mo);
252void __tsan_atomic32_store(volatile a32 *a, a32 v, int mo);
252253SANITIZER_INTERFACE_ATTRIBUTE
253void __tsan_atomic64_store(volatile a64 *a, a64 v, morder mo);
254void __tsan_atomic64_store(volatile a64 *a, a64 v, int mo);
254255#if __TSAN_HAS_INT128
255256SANITIZER_INTERFACE_ATTRIBUTE
256void __tsan_atomic128_store(volatile a128 *a, a128 v, morder mo);
257void __tsan_atomic128_store(volatile a128 *a, a128 v, int mo);
257258#endif
258259
259260SANITIZER_INTERFACE_ATTRIBUTE
260a8 __tsan_atomic8_exchange(volatile a8 *a, a8 v, morder mo);
261a8 __tsan_atomic8_exchange(volatile a8 *a, a8 v, int mo);
261262SANITIZER_INTERFACE_ATTRIBUTE
262a16 __tsan_atomic16_exchange(volatile a16 *a, a16 v, morder mo);
263a16 __tsan_atomic16_exchange(volatile a16 *a, a16 v, int mo);
263264SANITIZER_INTERFACE_ATTRIBUTE
264a32 __tsan_atomic32_exchange(volatile a32 *a, a32 v, morder mo);
265a32 __tsan_atomic32_exchange(volatile a32 *a, a32 v, int mo);
265266SANITIZER_INTERFACE_ATTRIBUTE
266a64 __tsan_atomic64_exchange(volatile a64 *a, a64 v, morder mo);
267a64 __tsan_atomic64_exchange(volatile a64 *a, a64 v, int mo);
267268#if __TSAN_HAS_INT128
268269SANITIZER_INTERFACE_ATTRIBUTE
269a128 __tsan_atomic128_exchange(volatile a128 *a, a128 v, morder mo);
270a128 __tsan_atomic128_exchange(volatile a128 *a, a128 v, int mo);
270271#endif
271272
272273SANITIZER_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);
274275SANITIZER_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);
276277SANITIZER_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);
278279SANITIZER_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);
280281#if __TSAN_HAS_INT128
281282SANITIZER_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);
283284#endif
284285
285286SANITIZER_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);
287288SANITIZER_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);
289290SANITIZER_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);
291292SANITIZER_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);
293294#if __TSAN_HAS_INT128
294295SANITIZER_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);
296297#endif
297298
298299SANITIZER_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);
300301SANITIZER_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);
302303SANITIZER_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);
304305SANITIZER_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);
306307#if __TSAN_HAS_INT128
307308SANITIZER_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);
309310#endif
310311
311312SANITIZER_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);
313314SANITIZER_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);
315316SANITIZER_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);
317318SANITIZER_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);
319320#if __TSAN_HAS_INT128
320321SANITIZER_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);
322323#endif
323324
324325SANITIZER_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);
326327SANITIZER_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);
328329SANITIZER_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);
330331SANITIZER_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);
332333#if __TSAN_HAS_INT128
333334SANITIZER_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);
335336#endif
336337
337338SANITIZER_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);
339340SANITIZER_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);
341342SANITIZER_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);
343344SANITIZER_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);
345346#if __TSAN_HAS_INT128
346347SANITIZER_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);
348349#endif
349350
350351SANITIZER_INTERFACE_ATTRIBUTE
351int __tsan_atomic8_compare_exchange_strong(volatile a8 *a, a8 *c, a8 v,
352 morder mo, morder fmo);
352int __tsan_atomic8_compare_exchange_strong(volatile a8 *a, a8 *c, a8 v, int mo,
353 int fmo);
353354SANITIZER_INTERFACE_ATTRIBUTE
354355int __tsan_atomic16_compare_exchange_strong(volatile a16 *a, a16 *c, a16 v,
355 morder mo, morder fmo);
356 int mo, int fmo);
356357SANITIZER_INTERFACE_ATTRIBUTE
357358int __tsan_atomic32_compare_exchange_strong(volatile a32 *a, a32 *c, a32 v,
358 morder mo, morder fmo);
359 int mo, int fmo);
359360SANITIZER_INTERFACE_ATTRIBUTE
360361int __tsan_atomic64_compare_exchange_strong(volatile a64 *a, a64 *c, a64 v,
361 morder mo, morder fmo);
362 int mo, int fmo);
362363#if __TSAN_HAS_INT128
363364SANITIZER_INTERFACE_ATTRIBUTE
364365int __tsan_atomic128_compare_exchange_strong(volatile a128 *a, a128 *c, a128 v,
365 morder mo, morder fmo);
366 int mo, int fmo);
366367#endif
367368
368369SANITIZER_INTERFACE_ATTRIBUTE
369int __tsan_atomic8_compare_exchange_weak(volatile a8 *a, a8 *c, a8 v, morder mo,
370 morder fmo);
370int __tsan_atomic8_compare_exchange_weak(volatile a8 *a, a8 *c, a8 v, int mo,
371 int fmo);
371372SANITIZER_INTERFACE_ATTRIBUTE
372373int __tsan_atomic16_compare_exchange_weak(volatile a16 *a, a16 *c, a16 v,
373 morder mo, morder fmo);
374 int mo, int fmo);
374375SANITIZER_INTERFACE_ATTRIBUTE
375376int __tsan_atomic32_compare_exchange_weak(volatile a32 *a, a32 *c, a32 v,
376 morder mo, morder fmo);
377 int mo, int fmo);
377378SANITIZER_INTERFACE_ATTRIBUTE
378379int __tsan_atomic64_compare_exchange_weak(volatile a64 *a, a64 *c, a64 v,
379 morder mo, morder fmo);
380 int mo, int fmo);
380381#if __TSAN_HAS_INT128
381382SANITIZER_INTERFACE_ATTRIBUTE
382383int __tsan_atomic128_compare_exchange_weak(volatile a128 *a, a128 *c, a128 v,
383 morder mo, morder fmo);
384 int mo, int fmo);
384385#endif
385386
386387SANITIZER_INTERFACE_ATTRIBUTE
387a8 __tsan_atomic8_compare_exchange_val(volatile a8 *a, a8 c, a8 v, morder mo,
388 morder fmo);
388a8 __tsan_atomic8_compare_exchange_val(volatile a8 *a, a8 c, a8 v, int mo,
389 int fmo);
389390SANITIZER_INTERFACE_ATTRIBUTE
390a16 __tsan_atomic16_compare_exchange_val(volatile a16 *a, a16 c, a16 v,
391 morder mo, morder fmo);
391a16 __tsan_atomic16_compare_exchange_val(volatile a16 *a, a16 c, a16 v, int mo,
392 int fmo);
392393SANITIZER_INTERFACE_ATTRIBUTE
393a32 __tsan_atomic32_compare_exchange_val(volatile a32 *a, a32 c, a32 v,
394 morder mo, morder fmo);
394a32 __tsan_atomic32_compare_exchange_val(volatile a32 *a, a32 c, a32 v, int mo,
395 int fmo);
395396SANITIZER_INTERFACE_ATTRIBUTE
396a64 __tsan_atomic64_compare_exchange_val(volatile a64 *a, a64 c, a64 v,
397 morder mo, morder fmo);
397a64 __tsan_atomic64_compare_exchange_val(volatile a64 *a, a64 c, a64 v, int mo,
398 int fmo);
398399#if __TSAN_HAS_INT128
399400SANITIZER_INTERFACE_ATTRIBUTE
400401a128 __tsan_atomic128_compare_exchange_val(volatile a128 *a, a128 c, a128 v,
401 morder mo, morder fmo);
402 int mo, int fmo);
402403#endif
403404
404405SANITIZER_INTERFACE_ATTRIBUTE
405void __tsan_atomic_thread_fence(morder mo);
406void __tsan_atomic_thread_fence(int mo);
406407SANITIZER_INTERFACE_ATTRIBUTE
407void __tsan_atomic_signal_fence(morder mo);
408void __tsan_atomic_signal_fence(int mo);
408409
409410SANITIZER_INTERFACE_ATTRIBUTE
410411void __tsan_go_atomic32_load(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
lib/tsan/tsan_interface_atomic.cpp+476-430
......@@ -18,9 +18,9 @@
1818// The following page contains more background information:
1919// http://www.hpl.hp.com/personal/Hans_Boehm/c++mm/
2020
21#include "sanitizer_common/sanitizer_mutex.h"
2122#include "sanitizer_common/sanitizer_placement_new.h"
2223#include "sanitizer_common/sanitizer_stacktrace.h"
23#include "sanitizer_common/sanitizer_mutex.h"
2424#include "tsan_flags.h"
2525#include "tsan_interface.h"
2626#include "tsan_rtl.h"
......@@ -34,8 +34,8 @@ static StaticSpinMutex mutex128;
3434
3535#if SANITIZER_DEBUG
3636static bool IsLoadOrder(morder mo) {
37 return mo == mo_relaxed || mo == mo_consume
38 || mo == mo_acquire || mo == mo_seq_cst;
37 return mo == mo_relaxed || mo == mo_consume || mo == mo_acquire ||
38 mo == mo_seq_cst;
3939}
4040
4141static bool IsStoreOrder(morder mo) {
......@@ -48,42 +48,49 @@ static bool IsReleaseOrder(morder mo) {
4848}
4949
5050static bool IsAcquireOrder(morder mo) {
51 return mo == mo_consume || mo == mo_acquire
52 || mo == mo_acq_rel || mo == mo_seq_cst;
51 return mo == mo_consume || mo == mo_acquire || mo == mo_acq_rel ||
52 mo == mo_seq_cst;
5353}
5454
5555static bool IsAcqRelOrder(morder mo) {
5656 return mo == mo_acq_rel || mo == mo_seq_cst;
5757}
5858
59template<typename T> T func_xchg(volatile T *v, T op) {
59template <typename T>
60T func_xchg(volatile T *v, T op) {
6061 T res = __sync_lock_test_and_set(v, op);
6162 // __sync_lock_test_and_set does not contain full barrier.
6263 __sync_synchronize();
6364 return res;
6465}
6566
66template<typename T> T func_add(volatile T *v, T op) {
67template <typename T>
68T func_add(volatile T *v, T op) {
6769 return __sync_fetch_and_add(v, op);
6870}
6971
70template<typename T> T func_sub(volatile T *v, T op) {
72template <typename T>
73T func_sub(volatile T *v, T op) {
7174 return __sync_fetch_and_sub(v, op);
7275}
7376
74template<typename T> T func_and(volatile T *v, T op) {
77template <typename T>
78T func_and(volatile T *v, T op) {
7579 return __sync_fetch_and_and(v, op);
7680}
7781
78template<typename T> T func_or(volatile T *v, T op) {
82template <typename T>
83T func_or(volatile T *v, T op) {
7984 return __sync_fetch_and_or(v, op);
8085}
8186
82template<typename T> T func_xor(volatile T *v, T op) {
87template <typename T>
88T func_xor(volatile T *v, T op) {
8389 return __sync_fetch_and_xor(v, op);
8490}
8591
86template<typename T> T func_nand(volatile T *v, T op) {
92template <typename T>
93T func_nand(volatile T *v, T op) {
8794 // clang does not support __sync_fetch_and_nand.
8895 T cmp = *v;
8996 for (;;) {
......@@ -95,7 +102,8 @@ template<typename T> T func_nand(volatile T *v, T op) {
95102 }
96103}
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) {
99107 return __sync_val_compare_and_swap(v, cmp, xch);
100108}
101109
......@@ -103,8 +111,8 @@ template<typename T> T func_cas(volatile T *v, T cmp, T xch) {
103111// Atomic ops are executed under tsan internal mutex,
104112// here we assume that the atomic variables are not accessed
105113// from non-instrumented code.
106#if !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) && !SANITIZER_GO \
107 && __TSAN_HAS_INT128
114#if !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) && !SANITIZER_GO && \
115 __TSAN_HAS_INT128
108116a128 func_xchg(volatile a128 *v, a128 op) {
109117 SpinMutexLock lock(&mutex128);
110118 a128 cmp = *v;
......@@ -197,89 +205,24 @@ static atomic_uint64_t *to_atomic(const volatile a64 *a) {
197205
198206static memory_order to_mo(morder mo) {
199207 switch (mo) {
200 case mo_relaxed: return memory_order_relaxed;
201 case mo_consume: return memory_order_consume;
202 case mo_acquire: return memory_order_acquire;
203 case mo_release: return memory_order_release;
204 case mo_acq_rel: return memory_order_acq_rel;
205 case mo_seq_cst: return memory_order_seq_cst;
208 case mo_relaxed:
209 return memory_order_relaxed;
210 case mo_consume:
211 return memory_order_consume;
212 case mo_acquire:
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;
206220 }
207221 DCHECK(0);
208222 return memory_order_seq_cst;
209223}
210224
211template<typename T>
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}
225namespace {
283226
284227template <typename T, T (*F)(volatile T *v, T op)>
285228static 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) {
303246 return v;
304247}
305248
306template<typename T>
307static T NoTsanAtomicExchange(volatile T *a, T v, morder mo) {
308 return func_xchg(a, v);
309}
249struct OpLoad {
250 template <typename T>
251 static T NoTsanAtomic(morder mo, const volatile T *a) {
252 return atomic_load(to_atomic(a), to_mo(mo));
253 }
310254
311template<typename T>
312static T NoTsanAtomicFetchAdd(volatile T *a, T v, morder mo) {
313 return func_add(a, v);
314}
255#if __TSAN_HAS_INT128 && !SANITIZER_GO
256 static a128 NoTsanAtomic(morder mo, const volatile a128 *a) {
257 SpinMutexLock lock(&mutex128);
258 return *a;
259 }
260#endif
315261
316template<typename T>
317static T NoTsanAtomicFetchSub(volatile T *a, T v, morder mo) {
318 return func_sub(a, v);
319}
262 template <typename T>
263 static T Atomic(ThreadState *thr, uptr pc, morder mo, const volatile T *a) {
264 DCHECK(IsLoadOrder(mo));
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>
322static T NoTsanAtomicFetchAnd(volatile T *a, T v, morder mo) {
323 return func_and(a, v);
324}
290struct OpStore {
291 template <typename T>
292 static void NoTsanAtomic(morder mo, volatile T *a, T v) {
293 atomic_store(to_atomic(a), v, to_mo(mo));
294 }
325295
326template<typename T>
327static T NoTsanAtomicFetchOr(volatile T *a, T v, morder mo) {
328 return func_or(a, v);
329}
296#if __TSAN_HAS_INT128 && !SANITIZER_GO
297 static void NoTsanAtomic(morder mo, volatile a128 *a, a128 v) {
298 SpinMutexLock lock(&mutex128);
299 *a = v;
300 }
301#endif
330302
331template<typename T>
332static T NoTsanAtomicFetchXor(volatile T *a, T v, morder mo) {
333 return func_xor(a, v);
334}
303 template <typename T>
304 static void Atomic(ThreadState *thr, uptr pc, morder mo, volatile T *a, T v) {
305 DCHECK(IsStoreOrder(mo));
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>
337static T NoTsanAtomicFetchNand(volatile T *a, T v, morder mo) {
338 return func_nand(a, v);
339}
327struct OpExchange {
328 template <typename T>
329 static T NoTsanAtomic(morder mo, volatile T *a, T v) {
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>
342static T AtomicExchange(ThreadState *thr, uptr pc, volatile T *a, T v,
343 morder mo) {
344 return AtomicRMW<T, func_xchg>(thr, pc, a, v, mo);
345}
338struct OpFetchAdd {
339 template <typename T>
340 static T NoTsanAtomic(morder mo, volatile T *a, T v) {
341 return func_add(a, v);
342 }
346343
347template<typename T>
348static T AtomicFetchAdd(ThreadState *thr, uptr pc, volatile T *a, T v,
349 morder mo) {
350 return AtomicRMW<T, func_add>(thr, pc, a, v, mo);
351}
344 template <typename T>
345 static T Atomic(ThreadState *thr, uptr pc, morder mo, volatile T *a, T v) {
346 return AtomicRMW<T, func_add>(thr, pc, a, v, mo);
347 }
348};
352349
353template<typename T>
354static T AtomicFetchSub(ThreadState *thr, uptr pc, volatile T *a, T v,
355 morder mo) {
356 return AtomicRMW<T, func_sub>(thr, pc, a, v, mo);
357}
350struct OpFetchSub {
351 template <typename T>
352 static T NoTsanAtomic(morder mo, volatile T *a, T v) {
353 return func_sub(a, v);
354 }
358355
359template<typename T>
360static T AtomicFetchAnd(ThreadState *thr, uptr pc, volatile T *a, T v,
361 morder mo) {
362 return AtomicRMW<T, func_and>(thr, pc, a, v, mo);
363}
356 template <typename T>
357 static T Atomic(ThreadState *thr, uptr pc, morder mo, volatile T *a, T v) {
358 return AtomicRMW<T, func_sub>(thr, pc, a, v, mo);
359 }
360};
364361
365template<typename T>
366static T AtomicFetchOr(ThreadState *thr, uptr pc, volatile T *a, T v,
367 morder mo) {
368 return AtomicRMW<T, func_or>(thr, pc, a, v, mo);
369}
362struct OpFetchAnd {
363 template <typename T>
364 static T NoTsanAtomic(morder mo, volatile T *a, T v) {
365 return func_and(a, v);
366 }
370367
371template<typename T>
372static T AtomicFetchXor(ThreadState *thr, uptr pc, volatile T *a, T v,
373 morder mo) {
374 return AtomicRMW<T, func_xor>(thr, pc, a, v, mo);
375}
368 template <typename T>
369 static T Atomic(ThreadState *thr, uptr pc, morder mo, volatile T *a, T v) {
370 return AtomicRMW<T, func_and>(thr, pc, a, v, mo);
371 }
372};
376373
377template<typename T>
378static T AtomicFetchNand(ThreadState *thr, uptr pc, volatile T *a, T v,
379 morder mo) {
380 return AtomicRMW<T, func_nand>(thr, pc, a, v, mo);
381}
374struct OpFetchOr {
375 template <typename T>
376 static T NoTsanAtomic(morder mo, volatile T *a, T v) {
377 return func_or(a, v);
378 }
382379
383template<typename T>
384static bool NoTsanAtomicCAS(volatile T *a, T *c, T v, morder mo, morder fmo) {
385 return atomic_compare_exchange_strong(to_atomic(a), c, v, to_mo(mo));
386}
380 template <typename T>
381 static T Atomic(ThreadState *thr, uptr pc, morder mo, volatile T *a, T v) {
382 return AtomicRMW<T, func_or>(thr, pc, a, v, mo);
383 }
384};
387385
388#if __TSAN_HAS_INT128
389static bool NoTsanAtomicCAS(volatile a128 *a, a128 *c, a128 v,
390 morder mo, morder fmo) {
391 a128 old = *c;
392 a128 cur = func_cas(a, old, v);
393 if (cur == old)
394 return true;
395 *c = cur;
396 return false;
397}
398#endif
386struct OpFetchXor {
387 template <typename T>
388 static T NoTsanAtomic(morder mo, volatile T *a, T v) {
389 return func_xor(a, v);
390 }
399391
400template<typename T>
401static T NoTsanAtomicCAS(volatile T *a, T c, T v, morder mo, morder fmo) {
402 NoTsanAtomicCAS(a, &c, v, mo, fmo);
403 return c;
404}
392 template <typename T>
393 static T Atomic(ThreadState *thr, uptr pc, morder mo, volatile T *a, T v) {
394 return AtomicRMW<T, func_xor>(thr, pc, a, v, mo);
395 }
396};
405397
406template <typename T>
407static bool AtomicCAS(ThreadState *thr, uptr pc, volatile T *a, T *c, T v,
408 morder mo, morder fmo) {
409 // 31.7.2.18: "The failure argument shall not be memory_order_release
410 // nor memory_order_acq_rel". LLVM (2021-05) fallbacks to Monotonic
411 // (mo_relaxed) when those are used.
412 DCHECK(IsLoadOrder(fmo));
398struct OpFetchNand {
399 template <typename T>
400 static T NoTsanAtomic(morder mo, volatile T *a, T v) {
401 return func_nand(a, v);
402 }
413403
414 MemoryAccess(thr, pc, (uptr)a, AccessSize<T>(), kAccessWrite | kAccessAtomic);
415 if (LIKELY(mo == mo_relaxed && fmo == mo_relaxed)) {
416 T cc = *c;
417 T pr = func_cas(a, cc, v);
418 if (pr == cc)
404 template <typename T>
405 static T Atomic(ThreadState *thr, uptr pc, morder mo, volatile T *a, T v) {
406 return AtomicRMW<T, func_nand>(thr, pc, a, v, mo);
407 }
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)
419422 return true;
420 *c = pr;
423 *c = cur;
421424 return false;
422425 }
423 SlotLocker locker(thr);
424 bool release = IsReleaseOrder(mo);
425 bool success;
426 {
427 auto s = ctx->metamap.GetSyncOrCreate(thr, pc, (uptr)a, false);
428 RWLock lock(&s->mtx, release);
429 T cc = *c;
430 T pr = func_cas(a, cc, v);
431 success = pr == cc;
432 if (!success) {
426#endif
427
428 template <typename T>
429 static T NoTsanAtomic(morder mo, morder fmo, volatile T *a, T c, T v) {
430 NoTsanAtomic(mo, fmo, a, &c, v);
431 return c;
432 }
433
434 template <typename T>
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;
433449 *c = pr;
434 mo = fmo;
450 return false;
435451 }
436 if (success && IsAcqRelOrder(mo))
437 thr->clock.ReleaseAcquire(&s->clock);
438 else if (success && IsReleaseOrder(mo))
439 thr->clock.Release(&s->clock);
440 else if (IsAcquireOrder(mo))
441 thr->clock.Acquire(s->clock);
452 SlotLocker locker(thr);
453 bool release = IsReleaseOrder(mo);
454 bool success;
455 {
456 auto s = ctx->metamap.GetSyncOrCreate(thr, pc, (uptr)a, false);
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;
442475 }
443 if (success && release)
444 IncrementEpoch(thr);
445 return success;
446}
447476
448template<typename T>
449static T AtomicCAS(ThreadState *thr, uptr pc,
450 volatile T *a, T c, T v, morder mo, morder fmo) {
451 AtomicCAS(thr, pc, a, &c, v, mo, fmo);
452 return c;
453}
477 template <typename T>
478 static T Atomic(ThreadState *thr, uptr pc, morder mo, morder fmo,
479 volatile T *a, T c, T v) {
480 Atomic(thr, pc, mo, fmo, a, &c, v);
481 return c;
482 }
483};
454484
455485#if !SANITIZER_GO
456static void NoTsanAtomicFence(morder mo) {
457 __sync_synchronize();
458}
486struct OpFence {
487 static void NoTsanAtomic(morder mo) { __sync_synchronize(); }
459488
460static void AtomicFence(ThreadState *thr, uptr pc, morder mo) {
461 // FIXME(dvyukov): not implemented.
462 __sync_synchronize();
463}
489 static void Atomic(ThreadState *thr, uptr pc, morder mo) {
490 // FIXME(dvyukov): not implemented.
491 __sync_synchronize();
492 }
493};
464494#endif
465495
496} // namespace
497
466498// Interface functions follow.
467499#if !SANITIZER_GO
468500
469501// C/C++
470502
471503static morder convert_morder(morder mo) {
472 if (flags()->force_seq_cst_atomics)
473 return (morder)mo_seq_cst;
504 return flags()->force_seq_cst_atomics ? mo_seq_cst : mo;
505}
474506
507static morder to_morder(int mo) {
475508 // Filter out additional memory order flags:
476509 // MEMMODEL_SYNC = 1 << 15
477510 // __ATOMIC_HLE_ACQUIRE = 1 << 16
......@@ -482,468 +515,481 @@ static morder convert_morder(morder mo) {
482515 // since we use __sync_ atomics for actual atomic operations,
483516 // we can safely ignore it as well. It also subtly affects semantics,
484517 // 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;
486521}
487522
488# define ATOMIC_IMPL(func, ...) \
489 ThreadState *const thr = cur_thread(); \
490 ProcessPendingSignals(thr); \
491 if (UNLIKELY(thr->ignore_sync || thr->ignore_interceptors)) \
492 return NoTsanAtomic##func(__VA_ARGS__); \
493 mo = convert_morder(mo); \
494 return Atomic##func(thr, GET_CALLER_PC(), __VA_ARGS__);
523template <class Op, class... Types>
524ALWAYS_INLINE auto AtomicImpl(morder mo, Types... args) {
525 ThreadState *const thr = cur_thread();
526 ProcessPendingSignals(thr);
527 if (UNLIKELY(thr->ignore_sync || thr->ignore_interceptors))
528 return Op::NoTsanAtomic(mo, args...);
529 return Op::Atomic(thr, GET_CALLER_PC(), convert_morder(mo), args...);
530}
495531
496532extern "C" {
497533SANITIZER_INTERFACE_ATTRIBUTE
498a8 __tsan_atomic8_load(const volatile a8 *a, morder mo) {
499 ATOMIC_IMPL(Load, a, mo);
534a8 __tsan_atomic8_load(const volatile a8 *a, int mo) {
535 return AtomicImpl<OpLoad>(to_morder(mo), a);
500536}
501537
502538SANITIZER_INTERFACE_ATTRIBUTE
503a16 __tsan_atomic16_load(const volatile a16 *a, morder mo) {
504 ATOMIC_IMPL(Load, a, mo);
539a16 __tsan_atomic16_load(const volatile a16 *a, int mo) {
540 return AtomicImpl<OpLoad>(to_morder(mo), a);
505541}
506542
507543SANITIZER_INTERFACE_ATTRIBUTE
508a32 __tsan_atomic32_load(const volatile a32 *a, morder mo) {
509 ATOMIC_IMPL(Load, a, mo);
544a32 __tsan_atomic32_load(const volatile a32 *a, int mo) {
545 return AtomicImpl<OpLoad>(to_morder(mo), a);
510546}
511547
512548SANITIZER_INTERFACE_ATTRIBUTE
513a64 __tsan_atomic64_load(const volatile a64 *a, morder mo) {
514 ATOMIC_IMPL(Load, a, mo);
549a64 __tsan_atomic64_load(const volatile a64 *a, int mo) {
550 return AtomicImpl<OpLoad>(to_morder(mo), a);
515551}
516552
517#if __TSAN_HAS_INT128
553# if __TSAN_HAS_INT128
518554SANITIZER_INTERFACE_ATTRIBUTE
519a128 __tsan_atomic128_load(const volatile a128 *a, morder mo) {
520 ATOMIC_IMPL(Load, a, mo);
555a128 __tsan_atomic128_load(const volatile a128 *a, int mo) {
556 return AtomicImpl<OpLoad>(to_morder(mo), a);
521557}
522#endif
558# endif
523559
524560SANITIZER_INTERFACE_ATTRIBUTE
525void __tsan_atomic8_store(volatile a8 *a, a8 v, morder mo) {
526 ATOMIC_IMPL(Store, a, v, mo);
561void __tsan_atomic8_store(volatile a8 *a, a8 v, int mo) {
562 return AtomicImpl<OpStore>(to_morder(mo), a, v);
527563}
528564
529565SANITIZER_INTERFACE_ATTRIBUTE
530void __tsan_atomic16_store(volatile a16 *a, a16 v, morder mo) {
531 ATOMIC_IMPL(Store, a, v, mo);
566void __tsan_atomic16_store(volatile a16 *a, a16 v, int mo) {
567 return AtomicImpl<OpStore>(to_morder(mo), a, v);
532568}
533569
534570SANITIZER_INTERFACE_ATTRIBUTE
535void __tsan_atomic32_store(volatile a32 *a, a32 v, morder mo) {
536 ATOMIC_IMPL(Store, a, v, mo);
571void __tsan_atomic32_store(volatile a32 *a, a32 v, int mo) {
572 return AtomicImpl<OpStore>(to_morder(mo), a, v);
537573}
538574
539575SANITIZER_INTERFACE_ATTRIBUTE
540void __tsan_atomic64_store(volatile a64 *a, a64 v, morder mo) {
541 ATOMIC_IMPL(Store, a, v, mo);
576void __tsan_atomic64_store(volatile a64 *a, a64 v, int mo) {
577 return AtomicImpl<OpStore>(to_morder(mo), a, v);
542578}
543579
544#if __TSAN_HAS_INT128
580# if __TSAN_HAS_INT128
545581SANITIZER_INTERFACE_ATTRIBUTE
546void __tsan_atomic128_store(volatile a128 *a, a128 v, morder mo) {
547 ATOMIC_IMPL(Store, a, v, mo);
582void __tsan_atomic128_store(volatile a128 *a, a128 v, int mo) {
583 return AtomicImpl<OpStore>(to_morder(mo), a, v);
548584}
549#endif
585# endif
550586
551587SANITIZER_INTERFACE_ATTRIBUTE
552a8 __tsan_atomic8_exchange(volatile a8 *a, a8 v, morder mo) {
553 ATOMIC_IMPL(Exchange, a, v, mo);
588a8 __tsan_atomic8_exchange(volatile a8 *a, a8 v, int mo) {
589 return AtomicImpl<OpExchange>(to_morder(mo), a, v);
554590}
555591
556592SANITIZER_INTERFACE_ATTRIBUTE
557a16 __tsan_atomic16_exchange(volatile a16 *a, a16 v, morder mo) {
558 ATOMIC_IMPL(Exchange, a, v, mo);
593a16 __tsan_atomic16_exchange(volatile a16 *a, a16 v, int mo) {
594 return AtomicImpl<OpExchange>(to_morder(mo), a, v);
559595}
560596
561597SANITIZER_INTERFACE_ATTRIBUTE
562a32 __tsan_atomic32_exchange(volatile a32 *a, a32 v, morder mo) {
563 ATOMIC_IMPL(Exchange, a, v, mo);
598a32 __tsan_atomic32_exchange(volatile a32 *a, a32 v, int mo) {
599 return AtomicImpl<OpExchange>(to_morder(mo), a, v);
564600}
565601
566602SANITIZER_INTERFACE_ATTRIBUTE
567a64 __tsan_atomic64_exchange(volatile a64 *a, a64 v, morder mo) {
568 ATOMIC_IMPL(Exchange, a, v, mo);
603a64 __tsan_atomic64_exchange(volatile a64 *a, a64 v, int mo) {
604 return AtomicImpl<OpExchange>(to_morder(mo), a, v);
569605}
570606
571#if __TSAN_HAS_INT128
607# if __TSAN_HAS_INT128
572608SANITIZER_INTERFACE_ATTRIBUTE
573a128 __tsan_atomic128_exchange(volatile a128 *a, a128 v, morder mo) {
574 ATOMIC_IMPL(Exchange, a, v, mo);
609a128 __tsan_atomic128_exchange(volatile a128 *a, a128 v, int mo) {
610 return AtomicImpl<OpExchange>(to_morder(mo), a, v);
575611}
576#endif
612# endif
577613
578614SANITIZER_INTERFACE_ATTRIBUTE
579a8 __tsan_atomic8_fetch_add(volatile a8 *a, a8 v, morder mo) {
580 ATOMIC_IMPL(FetchAdd, a, v, mo);
615a8 __tsan_atomic8_fetch_add(volatile a8 *a, a8 v, int mo) {
616 return AtomicImpl<OpFetchAdd>(to_morder(mo), a, v);
581617}
582618
583619SANITIZER_INTERFACE_ATTRIBUTE
584a16 __tsan_atomic16_fetch_add(volatile a16 *a, a16 v, morder mo) {
585 ATOMIC_IMPL(FetchAdd, a, v, mo);
620a16 __tsan_atomic16_fetch_add(volatile a16 *a, a16 v, int mo) {
621 return AtomicImpl<OpFetchAdd>(to_morder(mo), a, v);
586622}
587623
588624SANITIZER_INTERFACE_ATTRIBUTE
589a32 __tsan_atomic32_fetch_add(volatile a32 *a, a32 v, morder mo) {
590 ATOMIC_IMPL(FetchAdd, a, v, mo);
625a32 __tsan_atomic32_fetch_add(volatile a32 *a, a32 v, int mo) {
626 return AtomicImpl<OpFetchAdd>(to_morder(mo), a, v);
591627}
592628
593629SANITIZER_INTERFACE_ATTRIBUTE
594a64 __tsan_atomic64_fetch_add(volatile a64 *a, a64 v, morder mo) {
595 ATOMIC_IMPL(FetchAdd, a, v, mo);
630a64 __tsan_atomic64_fetch_add(volatile a64 *a, a64 v, int mo) {
631 return AtomicImpl<OpFetchAdd>(to_morder(mo), a, v);
596632}
597633
598#if __TSAN_HAS_INT128
634# if __TSAN_HAS_INT128
599635SANITIZER_INTERFACE_ATTRIBUTE
600a128 __tsan_atomic128_fetch_add(volatile a128 *a, a128 v, morder mo) {
601 ATOMIC_IMPL(FetchAdd, a, v, mo);
636a128 __tsan_atomic128_fetch_add(volatile a128 *a, a128 v, int mo) {
637 return AtomicImpl<OpFetchAdd>(to_morder(mo), a, v);
602638}
603#endif
639# endif
604640
605641SANITIZER_INTERFACE_ATTRIBUTE
606a8 __tsan_atomic8_fetch_sub(volatile a8 *a, a8 v, morder mo) {
607 ATOMIC_IMPL(FetchSub, a, v, mo);
642a8 __tsan_atomic8_fetch_sub(volatile a8 *a, a8 v, int mo) {
643 return AtomicImpl<OpFetchSub>(to_morder(mo), a, v);
608644}
609645
610646SANITIZER_INTERFACE_ATTRIBUTE
611a16 __tsan_atomic16_fetch_sub(volatile a16 *a, a16 v, morder mo) {
612 ATOMIC_IMPL(FetchSub, a, v, mo);
647a16 __tsan_atomic16_fetch_sub(volatile a16 *a, a16 v, int mo) {
648 return AtomicImpl<OpFetchSub>(to_morder(mo), a, v);
613649}
614650
615651SANITIZER_INTERFACE_ATTRIBUTE
616a32 __tsan_atomic32_fetch_sub(volatile a32 *a, a32 v, morder mo) {
617 ATOMIC_IMPL(FetchSub, a, v, mo);
652a32 __tsan_atomic32_fetch_sub(volatile a32 *a, a32 v, int mo) {
653 return AtomicImpl<OpFetchSub>(to_morder(mo), a, v);
618654}
619655
620656SANITIZER_INTERFACE_ATTRIBUTE
621a64 __tsan_atomic64_fetch_sub(volatile a64 *a, a64 v, morder mo) {
622 ATOMIC_IMPL(FetchSub, a, v, mo);
657a64 __tsan_atomic64_fetch_sub(volatile a64 *a, a64 v, int mo) {
658 return AtomicImpl<OpFetchSub>(to_morder(mo), a, v);
623659}
624660
625#if __TSAN_HAS_INT128
661# if __TSAN_HAS_INT128
626662SANITIZER_INTERFACE_ATTRIBUTE
627a128 __tsan_atomic128_fetch_sub(volatile a128 *a, a128 v, morder mo) {
628 ATOMIC_IMPL(FetchSub, a, v, mo);
663a128 __tsan_atomic128_fetch_sub(volatile a128 *a, a128 v, int mo) {
664 return AtomicImpl<OpFetchSub>(to_morder(mo), a, v);
629665}
630#endif
666# endif
631667
632668SANITIZER_INTERFACE_ATTRIBUTE
633a8 __tsan_atomic8_fetch_and(volatile a8 *a, a8 v, morder mo) {
634 ATOMIC_IMPL(FetchAnd, a, v, mo);
669a8 __tsan_atomic8_fetch_and(volatile a8 *a, a8 v, int mo) {
670 return AtomicImpl<OpFetchAnd>(to_morder(mo), a, v);
635671}
636672
637673SANITIZER_INTERFACE_ATTRIBUTE
638a16 __tsan_atomic16_fetch_and(volatile a16 *a, a16 v, morder mo) {
639 ATOMIC_IMPL(FetchAnd, a, v, mo);
674a16 __tsan_atomic16_fetch_and(volatile a16 *a, a16 v, int mo) {
675 return AtomicImpl<OpFetchAnd>(to_morder(mo), a, v);
640676}
641677
642678SANITIZER_INTERFACE_ATTRIBUTE
643a32 __tsan_atomic32_fetch_and(volatile a32 *a, a32 v, morder mo) {
644 ATOMIC_IMPL(FetchAnd, a, v, mo);
679a32 __tsan_atomic32_fetch_and(volatile a32 *a, a32 v, int mo) {
680 return AtomicImpl<OpFetchAnd>(to_morder(mo), a, v);
645681}
646682
647683SANITIZER_INTERFACE_ATTRIBUTE
648a64 __tsan_atomic64_fetch_and(volatile a64 *a, a64 v, morder mo) {
649 ATOMIC_IMPL(FetchAnd, a, v, mo);
684a64 __tsan_atomic64_fetch_and(volatile a64 *a, a64 v, int mo) {
685 return AtomicImpl<OpFetchAnd>(to_morder(mo), a, v);
650686}
651687
652#if __TSAN_HAS_INT128
688# if __TSAN_HAS_INT128
653689SANITIZER_INTERFACE_ATTRIBUTE
654a128 __tsan_atomic128_fetch_and(volatile a128 *a, a128 v, morder mo) {
655 ATOMIC_IMPL(FetchAnd, a, v, mo);
690a128 __tsan_atomic128_fetch_and(volatile a128 *a, a128 v, int mo) {
691 return AtomicImpl<OpFetchAnd>(to_morder(mo), a, v);
656692}
657#endif
693# endif
658694
659695SANITIZER_INTERFACE_ATTRIBUTE
660a8 __tsan_atomic8_fetch_or(volatile a8 *a, a8 v, morder mo) {
661 ATOMIC_IMPL(FetchOr, a, v, mo);
696a8 __tsan_atomic8_fetch_or(volatile a8 *a, a8 v, int mo) {
697 return AtomicImpl<OpFetchOr>(to_morder(mo), a, v);
662698}
663699
664700SANITIZER_INTERFACE_ATTRIBUTE
665a16 __tsan_atomic16_fetch_or(volatile a16 *a, a16 v, morder mo) {
666 ATOMIC_IMPL(FetchOr, a, v, mo);
701a16 __tsan_atomic16_fetch_or(volatile a16 *a, a16 v, int mo) {
702 return AtomicImpl<OpFetchOr>(to_morder(mo), a, v);
667703}
668704
669705SANITIZER_INTERFACE_ATTRIBUTE
670a32 __tsan_atomic32_fetch_or(volatile a32 *a, a32 v, morder mo) {
671 ATOMIC_IMPL(FetchOr, a, v, mo);
706a32 __tsan_atomic32_fetch_or(volatile a32 *a, a32 v, int mo) {
707 return AtomicImpl<OpFetchOr>(to_morder(mo), a, v);
672708}
673709
674710SANITIZER_INTERFACE_ATTRIBUTE
675a64 __tsan_atomic64_fetch_or(volatile a64 *a, a64 v, morder mo) {
676 ATOMIC_IMPL(FetchOr, a, v, mo);
711a64 __tsan_atomic64_fetch_or(volatile a64 *a, a64 v, int mo) {
712 return AtomicImpl<OpFetchOr>(to_morder(mo), a, v);
677713}
678714
679#if __TSAN_HAS_INT128
715# if __TSAN_HAS_INT128
680716SANITIZER_INTERFACE_ATTRIBUTE
681a128 __tsan_atomic128_fetch_or(volatile a128 *a, a128 v, morder mo) {
682 ATOMIC_IMPL(FetchOr, a, v, mo);
717a128 __tsan_atomic128_fetch_or(volatile a128 *a, a128 v, int mo) {
718 return AtomicImpl<OpFetchOr>(to_morder(mo), a, v);
683719}
684#endif
720# endif
685721
686722SANITIZER_INTERFACE_ATTRIBUTE
687a8 __tsan_atomic8_fetch_xor(volatile a8 *a, a8 v, morder mo) {
688 ATOMIC_IMPL(FetchXor, a, v, mo);
723a8 __tsan_atomic8_fetch_xor(volatile a8 *a, a8 v, int mo) {
724 return AtomicImpl<OpFetchXor>(to_morder(mo), a, v);
689725}
690726
691727SANITIZER_INTERFACE_ATTRIBUTE
692a16 __tsan_atomic16_fetch_xor(volatile a16 *a, a16 v, morder mo) {
693 ATOMIC_IMPL(FetchXor, a, v, mo);
728a16 __tsan_atomic16_fetch_xor(volatile a16 *a, a16 v, int mo) {
729 return AtomicImpl<OpFetchXor>(to_morder(mo), a, v);
694730}
695731
696732SANITIZER_INTERFACE_ATTRIBUTE
697a32 __tsan_atomic32_fetch_xor(volatile a32 *a, a32 v, morder mo) {
698 ATOMIC_IMPL(FetchXor, a, v, mo);
733a32 __tsan_atomic32_fetch_xor(volatile a32 *a, a32 v, int mo) {
734 return AtomicImpl<OpFetchXor>(to_morder(mo), a, v);
699735}
700736
701737SANITIZER_INTERFACE_ATTRIBUTE
702a64 __tsan_atomic64_fetch_xor(volatile a64 *a, a64 v, morder mo) {
703 ATOMIC_IMPL(FetchXor, a, v, mo);
738a64 __tsan_atomic64_fetch_xor(volatile a64 *a, a64 v, int mo) {
739 return AtomicImpl<OpFetchXor>(to_morder(mo), a, v);
704740}
705741
706#if __TSAN_HAS_INT128
742# if __TSAN_HAS_INT128
707743SANITIZER_INTERFACE_ATTRIBUTE
708a128 __tsan_atomic128_fetch_xor(volatile a128 *a, a128 v, morder mo) {
709 ATOMIC_IMPL(FetchXor, a, v, mo);
744a128 __tsan_atomic128_fetch_xor(volatile a128 *a, a128 v, int mo) {
745 return AtomicImpl<OpFetchXor>(to_morder(mo), a, v);
710746}
711#endif
747# endif
712748
713749SANITIZER_INTERFACE_ATTRIBUTE
714a8 __tsan_atomic8_fetch_nand(volatile a8 *a, a8 v, morder mo) {
715 ATOMIC_IMPL(FetchNand, a, v, mo);
750a8 __tsan_atomic8_fetch_nand(volatile a8 *a, a8 v, int mo) {
751 return AtomicImpl<OpFetchNand>(to_morder(mo), a, v);
716752}
717753
718754SANITIZER_INTERFACE_ATTRIBUTE
719a16 __tsan_atomic16_fetch_nand(volatile a16 *a, a16 v, morder mo) {
720 ATOMIC_IMPL(FetchNand, a, v, mo);
755a16 __tsan_atomic16_fetch_nand(volatile a16 *a, a16 v, int mo) {
756 return AtomicImpl<OpFetchNand>(to_morder(mo), a, v);
721757}
722758
723759SANITIZER_INTERFACE_ATTRIBUTE
724a32 __tsan_atomic32_fetch_nand(volatile a32 *a, a32 v, morder mo) {
725 ATOMIC_IMPL(FetchNand, a, v, mo);
760a32 __tsan_atomic32_fetch_nand(volatile a32 *a, a32 v, int mo) {
761 return AtomicImpl<OpFetchNand>(to_morder(mo), a, v);
726762}
727763
728764SANITIZER_INTERFACE_ATTRIBUTE
729a64 __tsan_atomic64_fetch_nand(volatile a64 *a, a64 v, morder mo) {
730 ATOMIC_IMPL(FetchNand, a, v, mo);
765a64 __tsan_atomic64_fetch_nand(volatile a64 *a, a64 v, int mo) {
766 return AtomicImpl<OpFetchNand>(to_morder(mo), a, v);
731767}
732768
733#if __TSAN_HAS_INT128
769# if __TSAN_HAS_INT128
734770SANITIZER_INTERFACE_ATTRIBUTE
735a128 __tsan_atomic128_fetch_nand(volatile a128 *a, a128 v, morder mo) {
736 ATOMIC_IMPL(FetchNand, a, v, mo);
771a128 __tsan_atomic128_fetch_nand(volatile a128 *a, a128 v, int mo) {
772 return AtomicImpl<OpFetchNand>(to_morder(mo), a, v);
737773}
738#endif
774# endif
739775
740776SANITIZER_INTERFACE_ATTRIBUTE
741int __tsan_atomic8_compare_exchange_strong(volatile a8 *a, a8 *c, a8 v,
742 morder mo, morder fmo) {
743 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
777int __tsan_atomic8_compare_exchange_strong(volatile a8 *a, a8 *c, a8 v, int mo,
778 int fmo) {
779 return AtomicImpl<OpCAS>(to_morder(mo), to_morder(fmo), a, c, v);
744780}
745781
746782SANITIZER_INTERFACE_ATTRIBUTE
747783int __tsan_atomic16_compare_exchange_strong(volatile a16 *a, a16 *c, a16 v,
748 morder mo, morder fmo) {
749 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
784 int mo, int fmo) {
785 return AtomicImpl<OpCAS>(to_morder(mo), to_morder(fmo), a, c, v);
750786}
751787
752788SANITIZER_INTERFACE_ATTRIBUTE
753789int __tsan_atomic32_compare_exchange_strong(volatile a32 *a, a32 *c, a32 v,
754 morder mo, morder fmo) {
755 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
790 int mo, int fmo) {
791 return AtomicImpl<OpCAS>(to_morder(mo), to_morder(fmo), a, c, v);
756792}
757793
758794SANITIZER_INTERFACE_ATTRIBUTE
759795int __tsan_atomic64_compare_exchange_strong(volatile a64 *a, a64 *c, a64 v,
760 morder mo, morder fmo) {
761 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
796 int mo, int fmo) {
797 return AtomicImpl<OpCAS>(to_morder(mo), to_morder(fmo), a, c, v);
762798}
763799
764#if __TSAN_HAS_INT128
800# if __TSAN_HAS_INT128
765801SANITIZER_INTERFACE_ATTRIBUTE
766802int __tsan_atomic128_compare_exchange_strong(volatile a128 *a, a128 *c, a128 v,
767 morder mo, morder fmo) {
768 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
803 int mo, int fmo) {
804 return AtomicImpl<OpCAS>(to_morder(mo), to_morder(fmo), a, c, v);
769805}
770#endif
806# endif
771807
772808SANITIZER_INTERFACE_ATTRIBUTE
773int __tsan_atomic8_compare_exchange_weak(volatile a8 *a, a8 *c, a8 v,
774 morder mo, morder fmo) {
775 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
809int __tsan_atomic8_compare_exchange_weak(volatile a8 *a, a8 *c, a8 v, int mo,
810 int fmo) {
811 return AtomicImpl<OpCAS>(to_morder(mo), to_morder(fmo), a, c, v);
776812}
777813
778814SANITIZER_INTERFACE_ATTRIBUTE
779815int __tsan_atomic16_compare_exchange_weak(volatile a16 *a, a16 *c, a16 v,
780 morder mo, morder fmo) {
781 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
816 int mo, int fmo) {
817 return AtomicImpl<OpCAS>(to_morder(mo), to_morder(fmo), a, c, v);
782818}
783819
784820SANITIZER_INTERFACE_ATTRIBUTE
785821int __tsan_atomic32_compare_exchange_weak(volatile a32 *a, a32 *c, a32 v,
786 morder mo, morder fmo) {
787 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
822 int mo, int fmo) {
823 return AtomicImpl<OpCAS>(to_morder(mo), to_morder(fmo), a, c, v);
788824}
789825
790826SANITIZER_INTERFACE_ATTRIBUTE
791827int __tsan_atomic64_compare_exchange_weak(volatile a64 *a, a64 *c, a64 v,
792 morder mo, morder fmo) {
793 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
828 int mo, int fmo) {
829 return AtomicImpl<OpCAS>(to_morder(mo), to_morder(fmo), a, c, v);
794830}
795831
796#if __TSAN_HAS_INT128
832# if __TSAN_HAS_INT128
797833SANITIZER_INTERFACE_ATTRIBUTE
798834int __tsan_atomic128_compare_exchange_weak(volatile a128 *a, a128 *c, a128 v,
799 morder mo, morder fmo) {
800 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
835 int mo, int fmo) {
836 return AtomicImpl<OpCAS>(to_morder(mo), to_morder(fmo), a, c, v);
801837}
802#endif
838# endif
803839
804840SANITIZER_INTERFACE_ATTRIBUTE
805a8 __tsan_atomic8_compare_exchange_val(volatile a8 *a, a8 c, a8 v,
806 morder mo, morder fmo) {
807 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
841a8 __tsan_atomic8_compare_exchange_val(volatile a8 *a, a8 c, a8 v, int mo,
842 int fmo) {
843 return AtomicImpl<OpCAS>(to_morder(mo), to_morder(fmo), a, c, v);
808844}
809845
810846SANITIZER_INTERFACE_ATTRIBUTE
811a16 __tsan_atomic16_compare_exchange_val(volatile a16 *a, a16 c, a16 v,
812 morder mo, morder fmo) {
813 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
847a16 __tsan_atomic16_compare_exchange_val(volatile a16 *a, a16 c, a16 v, int mo,
848 int fmo) {
849 return AtomicImpl<OpCAS>(to_morder(mo), to_morder(fmo), a, c, v);
814850}
815851
816852SANITIZER_INTERFACE_ATTRIBUTE
817a32 __tsan_atomic32_compare_exchange_val(volatile a32 *a, a32 c, a32 v,
818 morder mo, morder fmo) {
819 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
853a32 __tsan_atomic32_compare_exchange_val(volatile a32 *a, a32 c, a32 v, int mo,
854 int fmo) {
855 return AtomicImpl<OpCAS>(to_morder(mo), to_morder(fmo), a, c, v);
820856}
821857
822858SANITIZER_INTERFACE_ATTRIBUTE
823a64 __tsan_atomic64_compare_exchange_val(volatile a64 *a, a64 c, a64 v,
824 morder mo, morder fmo) {
825 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
859a64 __tsan_atomic64_compare_exchange_val(volatile a64 *a, a64 c, a64 v, int mo,
860 int fmo) {
861 return AtomicImpl<OpCAS>(to_morder(mo), to_morder(fmo), a, c, v);
826862}
827863
828#if __TSAN_HAS_INT128
864# if __TSAN_HAS_INT128
829865SANITIZER_INTERFACE_ATTRIBUTE
830866a128 __tsan_atomic128_compare_exchange_val(volatile a128 *a, a128 c, a128 v,
831 morder mo, morder fmo) {
832 ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
867 int mo, int fmo) {
868 return AtomicImpl<OpCAS>(to_morder(mo), to_morder(fmo), a, c, v);
833869}
834#endif
870# endif
835871
836872SANITIZER_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
839877SANITIZER_INTERFACE_ATTRIBUTE
840void __tsan_atomic_signal_fence(morder mo) {
841}
878void __tsan_atomic_signal_fence(int mo) {}
842879} // extern "C"
843880
844881#else // #if !SANITIZER_GO
845882
846883// Go
847884
848# define ATOMIC(func, ...) \
849 if (thr->ignore_sync) { \
850 NoTsanAtomic##func(__VA_ARGS__); \
851 } else { \
852 FuncEntry(thr, cpc); \
853 Atomic##func(thr, pc, __VA_ARGS__); \
854 FuncExit(thr); \
855 }
885template <class Op, class... Types>
886void AtomicGo(ThreadState *thr, uptr cpc, uptr pc, Types... args) {
887 if (thr->ignore_sync) {
888 (void)Op::NoTsanAtomic(args...);
889 } else {
890 FuncEntry(thr, cpc);
891 (void)Op::Atomic(thr, pc, args...);
892 FuncExit(thr);
893 }
894}
856895
857# define ATOMIC_RET(func, ret, ...) \
858 if (thr->ignore_sync) { \
859 (ret) = NoTsanAtomic##func(__VA_ARGS__); \
860 } else { \
861 FuncEntry(thr, cpc); \
862 (ret) = Atomic##func(thr, pc, __VA_ARGS__); \
863 FuncExit(thr); \
864 }
896template <class Op, class... Types>
897auto AtomicGoRet(ThreadState *thr, uptr cpc, uptr pc, Types... args) {
898 if (thr->ignore_sync) {
899 return Op::NoTsanAtomic(args...);
900 } else {
901 FuncEntry(thr, cpc);
902 auto ret = Op::Atomic(thr, pc, args...);
903 FuncExit(thr);
904 return ret;
905 }
906}
865907
866908extern "C" {
867909SANITIZER_INTERFACE_ATTRIBUTE
868910void __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);
870912}
871913
872914SANITIZER_INTERFACE_ATTRIBUTE
873915void __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);
875917}
876918
877919SANITIZER_INTERFACE_ATTRIBUTE
878920void __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));
880922}
881923
882924SANITIZER_INTERFACE_ATTRIBUTE
883925void __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));
885927}
886928
887929SANITIZER_INTERFACE_ATTRIBUTE
888930void __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));
890933}
891934
892935SANITIZER_INTERFACE_ATTRIBUTE
893936void __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));
895939}
896940
897941SANITIZER_INTERFACE_ATTRIBUTE
898942void __tsan_go_atomic32_fetch_and(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
899 ATOMIC_RET(FetchAnd, *(a32 *)(a + 16), *(a32 **)a, *(a32 *)(a + 8),
900 mo_acq_rel);
943 *(a32 *)(a + 16) = AtomicGoRet<OpFetchAnd>(thr, cpc, pc, mo_acq_rel,
944 *(a32 **)a, *(a32 *)(a + 8));
901945}
902946
903947SANITIZER_INTERFACE_ATTRIBUTE
904948void __tsan_go_atomic64_fetch_and(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
905 ATOMIC_RET(FetchAnd, *(a64 *)(a + 16), *(a64 **)a, *(a64 *)(a + 8),
906 mo_acq_rel);
949 *(a64 *)(a + 16) = AtomicGoRet<OpFetchAnd>(thr, cpc, pc, mo_acq_rel,
950 *(a64 **)a, *(a64 *)(a + 8));
907951}
908952
909953SANITIZER_INTERFACE_ATTRIBUTE
910954void __tsan_go_atomic32_fetch_or(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
911 ATOMIC_RET(FetchOr, *(a32 *)(a + 16), *(a32 **)a, *(a32 *)(a + 8),
912 mo_acq_rel);
955 *(a32 *)(a + 16) = AtomicGoRet<OpFetchOr>(thr, cpc, pc, mo_acq_rel,
956 *(a32 **)a, *(a32 *)(a + 8));
913957}
914958
915959SANITIZER_INTERFACE_ATTRIBUTE
916960void __tsan_go_atomic64_fetch_or(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
917 ATOMIC_RET(FetchOr, *(a64 *)(a + 16), *(a64 **)a, *(a64 *)(a + 8),
918 mo_acq_rel);
961 *(a64 *)(a + 16) = AtomicGoRet<OpFetchOr>(thr, cpc, pc, mo_acq_rel,
962 *(a64 **)a, *(a64 *)(a + 8));
919963}
920964
921965SANITIZER_INTERFACE_ATTRIBUTE
922966void __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));
924969}
925970
926971SANITIZER_INTERFACE_ATTRIBUTE
927972void __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));
929975}
930976
931977SANITIZER_INTERFACE_ATTRIBUTE
932void __tsan_go_atomic32_compare_exchange(
933 ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
934 a32 cur = 0;
935 a32 cmp = *(a32*)(a+8);
936 ATOMIC_RET(CAS, cur, *(a32**)a, cmp, *(a32*)(a+12), mo_acq_rel, mo_acquire);
937 *(bool*)(a+16) = (cur == cmp);
978void __tsan_go_atomic32_compare_exchange(ThreadState *thr, uptr cpc, uptr pc,
979 u8 *a) {
980 a32 cmp = *(a32 *)(a + 8);
981 a32 cur = AtomicGoRet<OpCAS>(thr, cpc, pc, mo_acq_rel, mo_acquire, *(a32 **)a,
982 cmp, *(a32 *)(a + 12));
983 *(bool *)(a + 16) = (cur == cmp);
938984}
939985
940986SANITIZER_INTERFACE_ATTRIBUTE
941void __tsan_go_atomic64_compare_exchange(
942 ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
943 a64 cur = 0;
944 a64 cmp = *(a64*)(a+8);
945 ATOMIC_RET(CAS, cur, *(a64**)a, cmp, *(a64*)(a+16), mo_acq_rel, mo_acquire);
946 *(bool*)(a+24) = (cur == cmp);
987void __tsan_go_atomic64_compare_exchange(ThreadState *thr, uptr cpc, uptr pc,
988 u8 *a) {
989 a64 cmp = *(a64 *)(a + 8);
990 a64 cur = AtomicGoRet<OpCAS>(thr, cpc, pc, mo_acq_rel, mo_acquire, *(a64 **)a,
991 cmp, *(a64 *)(a + 16));
992 *(bool *)(a + 24) = (cur == cmp);
947993}
948994} // extern "C"
949995#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) {
252252 if (AllocatorMayReturnNull())
253253 return SetErrnoOnNull(nullptr);
254254 GET_STACK_TRACE_FATAL(thr, pc);
255 ReportReallocArrayOverflow(size, n, &stack);
255 ReportReallocArrayOverflow(n, size, &stack);
256256 }
257257 return user_realloc(thr, pc, p, size * n);
258258}
lib/tsan/tsan_platform_linux.cpp-1
......@@ -418,7 +418,6 @@ void InitializePlatform() {
418418 Die();
419419 }
420420
421 InitTlsSize();
422421#endif // !SANITIZER_GO
423422}
424423
lib/tsan/tsan_rtl.cpp+4-1
......@@ -673,7 +673,8 @@ void CheckUnwind() {
673673 thr->ignore_reads_and_writes++;
674674 atomic_store_relaxed(&thr->in_signal_handler, 0);
675675#endif
676 PrintCurrentStackSlow(StackTrace::GetCurrentPc());
676 PrintCurrentStack(StackTrace::GetCurrentPc(),
677 common_flags()->fast_unwind_on_fatal);
677678}
678679
679680bool is_initialized;
......@@ -806,6 +807,7 @@ int Finalize(ThreadState *thr) {
806807
807808#if !SANITIZER_GO
808809void ForkBefore(ThreadState* thr, uptr pc) SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
810 VReport(2, "BeforeFork tid: %llu\n", GetTid());
809811 GlobalProcessorLock();
810812 // Detaching from the slot makes OnUserFree skip writing to the shadow.
811813 // The slot will be locked so any attempts to use it will deadlock anyway.
......@@ -847,6 +849,7 @@ static void ForkAfter(ThreadState* thr,
847849 SlotAttachAndLock(thr);
848850 SlotUnlock(thr);
849851 GlobalProcessorUnlock();
852 VReport(2, "AfterFork tid: %llu\n", GetTid());
850853}
851854
852855void 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);
514514StackID CurrentStackId(ThreadState *thr, uptr pc);
515515ReportStack *SymbolizeStackId(StackID stack_id);
516516void PrintCurrentStack(ThreadState *thr, uptr pc);
517void PrintCurrentStackSlow(uptr pc); // uses libunwind
517void PrintCurrentStack(uptr pc, bool fast); // may uses libunwind
518518MBlock *JavaHeapBlock(uptr addr, uptr *start);
519519
520520void Initialize(ThreadState *thr);
lib/tsan/tsan_rtl_report.cpp+5-5
......@@ -828,18 +828,18 @@ void PrintCurrentStack(ThreadState *thr, uptr pc) {
828828 PrintStack(SymbolizeStack(trace));
829829}
830830
831// Always inlining PrintCurrentStackSlow, because LocatePcInTrace assumes
831// Always inlining PrintCurrentStack, because LocatePcInTrace assumes
832832// __sanitizer_print_stack_trace exists in the actual unwinded stack, but
833// tail-call to PrintCurrentStackSlow breaks this assumption because
833// tail-call to PrintCurrentStack breaks this assumption because
834834// __sanitizer_print_stack_trace disappears after tail-call.
835835// However, this solution is not reliable enough, please see dvyukov's comment
836836// http://reviews.llvm.org/D19148#406208
837837// 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) {
839839#if !SANITIZER_GO
840840 uptr bp = GET_CURRENT_FRAME();
841841 auto *ptrace = New<BufferedStackTrace>();
842 ptrace->Unwind(pc, bp, nullptr, false);
842 ptrace->Unwind(pc, bp, nullptr, fast);
843843
844844 for (uptr i = 0; i < ptrace->size / 2; i++) {
845845 uptr tmp = ptrace->trace_buffer[i];
......@@ -857,6 +857,6 @@ using namespace __tsan;
857857extern "C" {
858858SANITIZER_INTERFACE_ATTRIBUTE
859859void __sanitizer_print_stack_trace() {
860 PrintCurrentStackSlow(StackTrace::GetCurrentPc());
860 PrintCurrentStack(StackTrace::GetCurrentPc(), false);
861861}
862862} // extern "C"
lib/tsan/tsan_rtl_thread.cpp+6-4
......@@ -165,14 +165,16 @@ void ThreadStart(ThreadState *thr, Tid tid, tid_t os_id,
165165#endif
166166
167167 uptr stk_addr = 0;
168 uptr stk_size = 0;
168 uptr stk_end = 0;
169169 uptr tls_addr = 0;
170 uptr tls_size = 0;
170 uptr tls_end = 0;
171171#if !SANITIZER_GO
172172 if (thread_type != ThreadType::Fiber)
173 GetThreadStackAndTls(tid == kMainTid, &stk_addr, &stk_size, &tls_addr,
174 &tls_size);
173 GetThreadStackAndTls(tid == kMainTid, &stk_addr, &stk_end, &tls_addr,
174 &tls_end);
175175#endif
176 uptr stk_size = stk_end - stk_addr;
177 uptr tls_size = tls_end - tls_addr;
176178 thr->stk_addr = stk_addr;
177179 thr->stk_size = stk_size;
178180 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{
410410 "sanitizer_allocator.cpp",
411411 "sanitizer_chained_origin_depot.cpp",
412412 "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",
416413 "sanitizer_deadlock_detector1.cpp",
417414 "sanitizer_deadlock_detector2.cpp",
418415 "sanitizer_errno.cpp",
......@@ -452,9 +449,7 @@ const sanitizer_common_sources = [_][]const u8{
452449 "sanitizer_tls_get_addr.cpp",
453450 "sanitizer_type_traits.cpp",
454451 "sanitizer_win.cpp",
455 "sanitizer_win_dll_thunk.cpp",
456 "sanitizer_win_dynamic_runtime_thunk.cpp",
457 "sanitizer_win_weak_interception.cpp",
452 "sanitizer_win_interception.cpp",
458453};
459454
460455const sanitizer_nolibc_sources = [_][]const u8{
......@@ -490,6 +485,7 @@ const sanitizer_symbolizer_sources = [_][]const u8{
490485 "sanitizer_symbolizer_report.cpp",
491486 "sanitizer_symbolizer_report_fuchsia.cpp",
492487 "sanitizer_symbolizer_win.cpp",
488 "sanitizer_thread_history.cpp",
493489 "sanitizer_unwind_linux_libcdep.cpp",
494490 "sanitizer_unwind_fuchsia.cpp",
495491 "sanitizer_unwind_win.cpp",